本文根據《大話數據結構》一書,實現了Java版的雙向鏈表。html
在每一個數據結點中都有兩個指針,分別指向直接後繼和直接前驅,這樣的鏈表稱爲雙向鏈表。java
雙向鏈表的結構如圖所示:node
雙向鏈表實現程序:數組
package DuLinkList; public class DuLinkList<E> { private Node<E> head; private int count; /** * 結點 */ class Node<E> { E data; Node<E> prior; Node<E> next; public Node(E data, Node<E> prior, Node<E> next) { this.data = data; this.prior = prior; this.next = next; } } /** * 線性表的初始化 */ public DuLinkList() { head = new Node<E>(null, null, null); head.prior = head.next = head; count = 0; } /** * 獲取第i個元素 */ public Node<E> getElement(int i) { if (count == 0) throw new RuntimeException("空表,沒法查找!"); if (i < 1 || i > count) throw new RuntimeException("查找位置錯誤!"); Node<E> node = head.next; for (int j = 1; j < i; j++) { node = node.next; } return node; } /** * 在第i個位置插入元素 */ public void listInsert(int i, E data) { if (i < 1 || i > count + 1) throw new RuntimeException("插入位置錯誤!"); Node<E> node = new Node<E>(data, null, null); if (i == 1) { node.next = head.next; node.prior = head; head.next.prior = node; head.next = node; } else { Node<E> pNode = getElement(i - 1); node.next = pNode.next; node.prior = pNode; pNode.next.prior = node; pNode.next = node; } count++; } /** * 刪除第i個元素 */ public E listDelete(int i) { if (i < 1 || i > count) throw new RuntimeException("刪除位置錯誤!"); Node<E> node = getElement(i); E e = node.data; if (i == 1) { head.next = node.next; node.next.prior = node.prior; node = null; } else { node.next.prior = node.prior; node.prior.next = node.next; node = null; } count--; return e; } public int listLength() { return count; } }
測試程序:數據結構
package DuLinkList; public class DuLinkListTest { public static void main(String[] args) { DuLinkList<Student> students = new DuLinkList<Student>(); System.out.println("——————————插入1到5,並讀取內容——————————"); Student[] stus = { new Student("小A", 11), new Student("小B", 12), new Student("小C", 13), new Student("小D", 14), new Student("小E", 151) }; for (int i = 1; i <= 5; i++) students.listInsert(i, stus[i - 1]); System.out.println("表長:" + students.listLength()); Student stu; for (int i = 1; i <= 5; i++) { stu = students.getElement(i).data; System.out.println("第" + i + "個位置爲:" + stu.name); } System.out.println("——————————刪除小A、小E——————————"); stu = students.listDelete(1); System.out.println("已刪除:" + stu.name); stu = students.listDelete(4); System.out.println("已刪除:" + stu.name); System.out.println("當前表長:" + students.listLength()); for (int i = 1; i <= students.listLength(); i++) { stu = students.getElement(i).data; System.out.println("第" + i + "個位置爲:" + stu.name); } } } class Student { public Student(String name, int age) { this.name = name; this.age = age; } String name; int age; }
——————————插入1到5,並讀取內容—————————— 表長:5 第1個位置爲:小A 第2個位置爲:小B 第3個位置爲:小C 第4個位置爲:小D 第5個位置爲:小E ——————————刪除小A、小E—————————— 已刪除:小A 已刪除:小E 當前表長:3 第1個位置爲:小B 第2個位置爲:小C 第3個位置爲:小D
——————————————————————————ide
在閱讀過他人的博客後,發現本身的查找方法沒有利用好雙鏈表的特性,重寫查找方法以下:post
/** * 獲取第i個元素 */ public Node<E> getElement(int i) { if (count == 0) throw new RuntimeException("空表,沒法查找!"); if (i < 1 || i > count) throw new RuntimeException("查找位置錯誤!"); if (i <= count / 2) { // 正向查找 Node<E> node = head.next; for (int j = 1; j < i; j++) { node = node.next; } return node; } else { // 反向查找 Node<E> node = head.prior; int k = count - i; for (int j = 0; j < k; j++) { node = node.prior; } return node; } }
本文中只編寫了查找和刪除部分的程序,完整的雙向鏈表程序可參閱這篇博客:數組、單鏈表和雙鏈表介紹 以及 雙向鏈表的C/C++/Java實現測試