一、双向链表的结构。 (1)、首先节点的结构,其中包含本节点内容,同时需要知道前面是谁后面是谁。 Java代码 private static class Entry<E> { //元素 E e; //后一个节点 Entry<E> nextEntry; //前一个节点 Entry<E> previousEntry; public Entry(E e, Entry<E> previousEntry, Entry<E> nextEntry) { this.e = e; this.nextEntry = nextEntry; this.previousEntry = previousEntry; } } private static class Entry<E> { //元素 E e; //后一个节点 Entry<E> nextEntry; //前一个节点 Entry<E> previousEntry; public Entry(E e, Entry<E> previousEntry, Entry<E> nextEntry) { this.e = e; this.nextEntry = nextEntry; this.previousEntry = previousEntry; } } 其中e则指向本节点的元素,而nextEntry则指向下一个节点,previousEntry则指向前一个节点。 (2)、需要定义一个节点,其同时知道表头,同时知道表尾,这里就暂时定义为head。 Java代码 private transient Entry<E> head = new Entry<E>(null, null, null); public DoubleChain() { head.nextEntry = head.previousEntry = head; } private transient Entry<E> head = new Entry<E>(null, null, null); public DoubleChain() { head.nextEntry = head.previousEntry = head; } 可以看出,在初始化方法中,直接将表头和表尾直接都指向head。这样在head的基础上不管怎么增加元素都逃脱不了与head关系。牢记head.nextEntry表头,head.previousEntry表尾。 (3)、同样记录节点的个数只是为了提高效率,不是必要。 Java代码 private int size; public int size() { return this.size; } private int size; public int size() { return this.size; } Java代码 好了有这三样,就足够了。就看我们如何用他们了。 二、内部实现。 (1)、方法addBefore。由于一开始就初始化了head,有了head作为基准,玩转整个链表也就靠这个方法了。 Java代码 private void addBefore(E e, Entry<E> entry) { //新节点的初始化,指定新节点的前一个节点和后一个节点 Entry<E> newEntry = new Entry<E>(e, entry.previousEntry, entry); //告知新节点的前一个节点其后面是新节点 newEntry.previousEntry.nextEntry = newEntry; //告知新节点的后一个节点其前节点是新节点 newEntry.nextEntry.previousEntry = newEntry; size++; } private void addBefore(E e, Entry<E> entry) { //新节点的初始化,指定新节点的前一个节点和后一个节点 Entry<E> newEntry = new Entry<E>(e, entry.previousEntry, entry); //告知新节点的前一个节点其后面是新节点 newEntry.previousEntry.nextEntry = newEntry; //告知新节点的后一个节点其前节点是新节点 newEntry.nextEntry.previousEntry = newEntry; size++; } 可以看出,通过指定的元素创建一个新的节点。然后将其前前后后的关系都打通就好了。 (2)、表头插入。再简单不过了,直接在head.nextEntry前增加就好了,直接调用addBefore。效率高 Java代码 public void addHead(E e) { this.addBefore(e, head.nextEntry); } public void addHead(E e) { this.addBefore(e, head.nextEntry); } (3)、尾插入。同样简单,直接在head.previous前增加就好了,同样调用addBefore。效率高 Java代码 public void add(E e) { this.addBefore(e, head); } public void add(E e) { this.addBefore(e, head); } (4)、指定节点插入(插队)。同样需要插队,但是由于其节点的双向性,则不需要进行特殊处理,直接循环找出指定的节点元素就好了。效率低 Java代码 public void addSpecifyIndex(E e, int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { this.addBefore(e, p); return; } count++; } } public void addSpecifyIndex(E e, int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { this.addBefore(e, p); return; } count++; } } (5)、指定节点获取元素。同样循环找出。效率低 Java代码 public E get(int index) { int count = 0; E result = null; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { result = p.e; } count++; } return result; } public E get(int index) { int count = 0; E result = null; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { result = p.e; } count++; } return result; } (6)、指定节点删除。同理,找到要删除的节点,让指定节点的前后直接相通就OK了。效率低 Java代码 public void remove(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { p.previousEntry.nextEntry= p.nextEntry; p.nextEntry.previousEntry=p.previousEntry; size--; return; } count++; } } public void remove(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { p.previousEntry.nextEntry= p.nextEntry; p.nextEntry.previousEntry=p.previousEntry; size--; return; } count++; } } (7)、循环。为了好进行遍历演示,下面的就是循环遍历所用的了,大家随意看一下就好了。 Java代码 private Entry<E> current; public boolean hasNext() { return current != head; } public E next() { E result = current.e; current = current.nextEntry; return result; } public void setCursor(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { current = p; } count++; } private Entry<E> current; public boolean hasNext() { return current != head; } public E next() { E result = current.e; current = current.nextEntry; return result; } public void setCursor(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { current = p; } count++; } 三、测试。。一个main方法,测试一下。 Java代码 public static void main(String[] args) { DoubleChain<String> doubleChain = new DoubleChain<String>(); for (int i = 0; i < 4; i++) { doubleChain.add(i + ""); } // 头插入 // doubleChain.addHead("head"); // // 尾插入 // doubleChain.add("tail"); // // 指定节点插入 // doubleChain.addSpecifyIndex("Specify", 1); // // 指定节点删除 // doubleChain.remove(3); // // 设置循环的初始节点 // doubleChain.setCursor(0); int count = 0; System.out.println("######SIZE" + doubleChain.size() + "#######"); while (doubleChain.hasNext()) { System.out.println("index:" + count + ",entry:" + doubleChain.next()); count++; } System.out.println(doubleChain.get(doubleChain.size() - 2)); } public static void main(String[] args) { DoubleChain<String> doubleChain = new DoubleChain<String>(); for (int i = 0; i < 4; i++) { doubleChain.add(i + ""); } // 头插入 // doubleChain.addHead("head"); // // 尾插入 // doubleChain.add("tail"); // // 指定节点插入 // doubleChain.addSpecifyIndex("Specify", 1); // // 指定节点删除 // doubleChain.remove(3); // // 设置循环的初始节点 // doubleChain.setCursor(0); int count = 0; System.out.println("######SIZE" + doubleChain.size() + "#######"); while (doubleChain.hasNext()) { System.out.println("index:" + count + ",entry:" + doubleChain.next()); count++; } System.out.println(doubleChain.get(doubleChain.size() - 2)); } 四、总结。。 可以看出,从结构上讲,双向链表和单项链表最大的区别在于每个节点都是双向的。从效率上讲,提高了尾插入的效率,但是对于插队同样效率不高。如果需要反复进行插队操作的同学注意了,LinkedList的效率会很低的哦。 五、全部代码。。 Java代码 package paladin.chain; public class DoubleChain<E> implements Chain<E> { private transient Entry<E> head = new Entry<E>(null, null, null); private Entry<E> current; private int size; public DoubleChain() { head.nextEntry = head.previousEntry = head; } private void addBefore(E e, Entry<E> entry) { //新节点的初始化,指定新节点的前一个节点和后一个节点 Entry<E> newEntry = new Entry<E>(e, entry.previousEntry, entry); //告知新节点的前一个节点其后面是新节点 newEntry.previousEntry.nextEntry = newEntry; //告知新节点的后一个节点其前节点是新节点 newEntry.nextEntry.previousEntry = newEntry; size++; } public void add(E e) { this.addBefore(e, head); } public void addHead(E e) { this.addBefore(e, head.nextEntry); } public void addSpecifyIndex(E e, int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { this.addBefore(e, p); return; } count++; } } public void remove(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { p.previousEntry.nextEntry= p.nextEntry; p.nextEntry.previousEntry=p.previousEntry; size--; return; } count++; } } public E get(int index) { int count = 0; E result = null; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { result = p.e; } count++; } return result; } public boolean hasNext() { return current != head; } public E next() { E result = current.e; current = current.nextEntry; return result; } public void setCursor(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { current = p; } count++; } } public int size() { return this.size; } private static class Entry<E> { //元素 E e; //后一个节点 Entry<E> nextEntry; //前一个节点 Entry<E> previousEntry; public Entry(E e, Entry<E> previousEntry, Entry<E> nextEntry) { this.e = e; this.nextEntry = nextEntry; this.previousEntry = previousEntry; } } public static void main(String[] args) { DoubleChain<String> doubleChain = new DoubleChain<String>(); for (int i = 0; i < 4; i++) { doubleChain.add(i + ""); } // 头插入 // doubleChain.addHead("head"); // // 尾插入 // doubleChain.add("tail"); // // 指定节点插入 // doubleChain.addSpecifyIndex("Specify", 1); // // 指定节点删除 // doubleChain.remove(3); // // 设置循环的初始节点 // doubleChain.setCursor(0); int count = 0; System.out.println("######SIZE" + doubleChain.size() + "#######"); while (doubleChain.hasNext()) { System.out.println("index:" + count + ",entry:" + doubleChain.next()); count++; } System.out.println(doubleChain.get(doubleChain.size() - 2)); } } package paladin.chain; public class DoubleChain<E> implements Chain<E> { private transient Entry<E> head = new Entry<E>(null, null, null); private Entry<E> current; private int size; public DoubleChain() { head.nextEntry = head.previousEntry = head; } private void addBefore(E e, Entry<E> entry) { //新节点的初始化,指定新节点的前一个节点和后一个节点 Entry<E> newEntry = new Entry<E>(e, entry.previousEntry, entry); //告知新节点的前一个节点其后面是新节点 newEntry.previousEntry.nextEntry = newEntry; //告知新节点的后一个节点其前节点是新节点 newEntry.nextEntry.previousEntry = newEntry; size++; } public void add(E e) { this.addBefore(e, head); } public void addHead(E e) { this.addBefore(e, head.nextEntry); } public void addSpecifyIndex(E e, int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { this.addBefore(e, p); return; } count++; } } public void remove(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { p.previousEntry.nextEntry= p.nextEntry; p.nextEntry.previousEntry=p.previousEntry; size--; return; } count++; } } public E get(int index) { int count = 0; E result = null; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { result = p.e; } count++; } return result; } public boolean hasNext() { return current != head; } public E next() { E result = current.e; current = current.nextEntry; return result; } public void setCursor(int index) { int count = 0; for (Entry<E> p = head.nextEntry; p != head; p = p.nextEntry) { if (count == index) { current = p; } count++; } } public int size() { return this.size; } private static class Entry<E> { //元素 E e; //后一个节点 Entry<E> nextEntry; //前一个节点 Entry<E> previousEntry; public Entry(E e, Entry<E> previousEntry, Entry<E> nextEntry) { this.e = e; this.nextEntry = nextEntry; this.previousEntry = previousEntry; } } public static void main(String[] args) { DoubleChain<String> doubleChain = new DoubleChain<String>(); for (int i = 0; i < 4; i++) { doubleChain.add(i + ""); } // 头插入 // doubleChain.addHead("head"); // // 尾插入 // doubleChain.add("tail"); // // 指定节点插入 // doubleChain.addSpecifyIndex("Specify", 1); // // 指定节点删除 // doubleChain.remove(3); // // 设置循环的初始节点 // doubleChain.setCursor(0); int count = 0; System.out.println("######SIZE" + doubleChain.size() + "#######"); while (doubleChain.hasNext()) { System.out.println("index:" + count + ",entry:" + doubleChain.next()); count++; } System.out.println(doubleChain.get(doubleChain.size() - 2)); } }