文章目录
- 数据结构--双向链表
- 前言
- 一、双向链表的结构
- 添加元素操作说明:
- 删除元素操作说明:
- 二、代码实现
- 总结
前言
在上一篇文章中介绍了单向链表的结构以及实现,本篇文章再来介绍另一种链表——双向链表。
一、双向链表的结构双向链表是链表的一种,与单向链表均由若干个节点组成,每个节点包含数据域和指针域,不同的是,双向链表每个节点有两个指针域和一个数据域,其中一个指针指向前驱元素,另一个指针指向后继元素,如图:
在添加元素时,除了要完成使新节点前一个节点的next指向新节点,新节点的next指向后一个节点外,因为是双向的,还要使新节点的pre指向前一个节点,新节点后一个节点的pre指向新节点(此处有点绕)。
删除元素时,是被删除元素的前一个节点的next指向被删除元素后一个节点;被删除元素后一个节点的pre指向被删除元素的前一个节点。
链表实现以及相关方法完整代码:
package sequence; import java.util.Iterator; public class TwoWayLinkListimplements Iterable { //首节点 private Node head; //尾节点 private Node last; //链表长度 private int N; private class Node { //数据域 public T item; //指向上一个节点 public Node pre; //指向下一个节点 public Node next; public Node(T item, Node pre, Node next) { this.item = item; this.pre = pre; this.next = next; } } public TwoWayLinkList() { //初始化头节点和尾节点 this.head = new Node(null, null, null); this.last = null; //初始化元素个数 this.N = 0; } //空置线性表 public void clear() { this.head.next = null; this.last = null; this.N = 0; } //判断线性表是否为空 public boolean isEmpty() { return N == 0; } //获取线性表中元素的个数 public int length() { return N; } //读取并返回线性表中第i个元素 public T get(int i) { Node n = head.next; for(int index = 0; index < i; index++){ n = n.next; } return n.item; } //向线性表中添加一个元素 public void insert(T t) { //当线性表为空时: if (isEmpty()) { //创建一个新节点 Node newNode = new Node(t, head, null); //使新节点成为尾节点: last = newNode; //使头节点指向尾节点; head.next = last; } else { Node oldLast = last; //当链表不为空时: //创建一个新节点: Node newNode = new Node(t, oldLast, null); //使当前尾节点指向新节点: oldLast.next = newNode; //使新节点成为尾节点: last = newNode; } N++; } //向线性表中第i个元素之前添加一个值为t的元素 public void insert(int i, T t) { Node pre = head; //找到i位置的前一个节点: for (int index = 0; index < i; index++) { pre = pre.next; } //找到i位置的节点: Node currNode = pre.next; //创建新节点: Node newNode = new Node(t, pre, currNode); //使i位置的节点的pre指向新节点: currNode.pre = newNode; //使i位置的前一个节点的next指向新节点: pre.next = newNode; N++; } //删除并返回线性表中第i个数据元素 public T remove(int i) { Node pre = head; //找到i位置的前一个节点: for(int index = 0; index < i; index++){ pre = pre.next; } //找到i位置的节点: Node curNode = pre.next; //找到i位置的下一个节点: Node nextNode = curNode.next; //使i位置节点的前一个节点的next指向i位置后的节点; pre.next = nextNode; //使i位置后的节点的pre指向i位置前的节点: nextNode.pre = pre; N--; return curNode.item; } //返回线性表中首次出现指定元素的下标,若不存在,则返回-1 public int indexOf(T t) { Node n = head; for(int index = 0; n.next != null; index++){ n = n.next; if(t.equals(n.item)){ return index; } } return -1; } //获取第一个元素 public T getFirst() { if (isEmpty()) { return null; } return head.next.item; } //获取最后一个元素 public T getLast() { if (isEmpty()) { return null; } return last.item; } //提供遍历方式 @Override public Iterator iterator() { return new TIterator(); } private class TIterator implements Iterator{ private Node n; public TIterator(){ this.n = head; } @Override public boolean hasNext() { return n.next != null; } @Override public Object next() { n = n.next; return n.item; } } }
总结
Java集合中的LinkedList的实现就是一个双向链表,可以查看底层的相关代码去验证。



