双向链表(DoublyLinkedList)的实现【java】

In computer science, a doubly linked list is a linked data structure that consists of a set of sequentially linked records called nodes. Each node contains two fields, called links, that are references to the previous and to the next node in the sequence of nodes. The beginning and ending nodes'previous and next links, respectively, point to some kind of terminator, typically a sentinel node or null, to facilitate traversal of the list. If there is only one sentinel node, then the list is circularly linked via the sentinel node. It can be conceptualized as two singly linked lists formed from the same data items, but in opposite sequential orders.

The two node links allow traversal of the list in either direction. While adding or removing a node in a doubly linked list requires changing more links than the same operations on a singly linked list, the operations are simpler and potentially more efficient (for nodes other than first nodes) because there is no need to keep track of the previous node during traversal or no need to traverse the list to find the previous node, so that its link can be modified.

                               --from wikipedia(http://en.wikipedia.org/wiki/Doubly_linked_list)

 

1、双向链表的节点

Node
 1 package com.matrix.doublylinkedlist;
2
3 //双向链表的节点
4 public class Node<T> {
5
6 // 节点数据域
7 public T data;
8 // 节点的prev指针
9 public Node<T> prev = null;
10 // 节点的next指针
11 public Node<T> next = null;
12
13 public boolean equals(Node<T> node) {
14 if (data.equals(node.data)) {
15 return true;
16 }
17 return false;
18 }
19
20 public int hashCode() {
21 return data.hashCode();
22 }
23
24 public String toString() {
25 return data.toString();
26 }
27 }

2、双向链表封转类

DoublyLinkedList
  1 package com.matrix.doublylinkedlist;
2
3 public class DoublyLinkedList<T> {
4
5 // 双向链表的头指针
6 private Node<T> head;
7
8 // 双向链表的尾指针
9 private Node<T> tail;
10
11 public DoublyLinkedList() {
12 head = new Node<T>();
13 tail = new Node<T>();
14 }
15
16 // 添加节点到链表的头部
17 public void addToHead(Node<T> node) {
18 if (null == head.next) {
19 head.next = node;
20 tail.prev = node;
21 } else {
22 node.next = head.next;
23 head.next.prev = node;
24 head.next = node;
25 }
26 }
27
28 // 添加节点到链表的尾部
29 public void addToTail(Node<T> node) {
30 if (null == tail.prev) {
31 tail.prev = node;
32 head.next = node;
33 } else {
34 tail.prev.next = node;
35 node.prev = tail.prev;
36 tail.prev = node;
37 }
38 }
39
40 // 链表的遍历(从head顺序遍历)
41 public void traversalFromHead() {
42 if (isEmpty()) {
43 System.out.println("The Doubly Linked List is empry");
44 } else {
45 Node<T> node = head;
46 while (null != node.next) {
47 System.out.print(node.next + "-->");
48 node = node.next;
49 }
50 System.out.println();
51 }
52 }
53
54 // 链表的遍历(从tail倒序遍历)
55 public void traversalFromTail() {
56 if (isEmpty()) {
57 System.out.println("The Doubly Linked List is empty");
58 } else {
59 Node<T> node = tail;
60 while (null != node.prev) {
61 System.out.print(node.prev+ "-->");
62 node = node.prev;
63 }
64 System.out.println();
65 }
66 }
67
68 // 添加某个值到指定的数值的节点后面
69 public void insertAfter(Node<T> node, T key) {
70 if (null == head.next || null == tail.prev) {
71 System.out.println("The Doubly Linked List is empty");
72 } else {
73 Node<T> theNode = head;
74 while (null != theNode.next) {
75 if (theNode.next.data.equals(key)) {
76 node.next = theNode.next.next;
77 theNode.next.next.prev = node;
78 theNode.next.next = node;
79 node.prev = theNode.next;
80 break;
81 }
82 theNode = theNode.next;
83 }
84 }
85 }
86
87 // 添加某个值到指定的数值的节点前面
88 public void insertBefore(Node<T> node, T key) {
89 if (null == head.next || null == tail.prev) {
90 System.out.println("The Doubly Linked List is empty");
91 } else {
92 Node<T> theNode = head;
93 while (null != theNode.next) {
94 if (theNode.next.data.equals(key)) {
95 node.next = theNode.next;
96 theNode.next.prev = node;
97 theNode.next = node;
98 node.prev = theNode;
99 break;
100 }
101 theNode = theNode.next;
102 }
103 }
104 }
105
106 // 判断链表是否为空
107 public boolean isEmpty() {
108 if (null == head.next || null == tail.prev) {
109 return true;
110 }
111 return false;
112 }
113
114 }

3、双向链表测试类

DoublyLinkedListTest
 1 package com.matrix.doublylinkedlist;
2
3 import org.junit.Test;
4
5 public class DoublyLinkedListTest {
6
7 @Test
8 public void test() {
9
10 DoublyLinkedList<Integer> doublyLinkedList = new DoublyLinkedList<Integer>();
11 for (int i = 0; i < 6; i++) {
12 Node<Integer> node = new Node<Integer>();
13 node.data = i;
14 doublyLinkedList.addToHead(node);
15 }
16 doublyLinkedList.traversalFromHead();
17 doublyLinkedList.traversalFromTail();
18 System.out.println("---------------------------");
19 for (int i = 10; i < 16; i++) {
20 Node<Integer> node = new Node<Integer>();
21 node.data = i;
22 doublyLinkedList.addToHead(node);
23 }
24 Node<Integer> node = new Node<Integer>();
25 node.data = 88;
26 doublyLinkedList.insertAfter(node, 11);
27 doublyLinkedList.traversalFromHead();
28 doublyLinkedList.traversalFromTail();
29
30 Node<Integer> node1 = new Node<Integer>();
31 node1.data = 99;
32 doublyLinkedList.insertBefore(node1, 14);
33 doublyLinkedList.traversalFromHead();
34 doublyLinkedList.traversalFromTail();
35 }
36 }

 

一步一步往上爬......

转载于:https://www.cnblogs.com/matrix1024/archive/2011/12/31/2308380.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是双链表类DoublyLinkedList的声明和实现: ``` public class DoublyLinkedList<T> implements LList<T> { private Node<T> head; private Node<T> tail; private int size; private static class Node<T> { T data; Node<T> next; Node<T> prev; Node(T data) { this.data = data; this.next = null; this.prev = null; } } public DoublyLinkedList() { head = null; tail = null; size = 0; } @Override public boolean isEmpty() { return size == 0; } @Override public int size() { return size; } @Override public void addFirst(T data) { Node<T> newNode = new Node<>(data); if (isEmpty()) { head = tail = newNode; } else { newNode.next = head; head.prev = newNode; head = newNode; } size++; } @Override public void addLast(T data) { Node<T> newNode = new Node<>(data); if (isEmpty()) { head = tail = newNode; } else { newNode.prev = tail; tail.next = newNode; tail = newNode; } size++; } @Override public void add(int index, T data) { if (index < 0 || index > size) { throw new IndexOutOfBoundsException("Invalid index"); } if (index == 0) { addFirst(data); } else if (index == size) { addLast(data); } else { Node<T> newNode = new Node<>(data); Node<T> current = head; for (int i = 0; i < index; i++) { current = current.next; } newNode.prev = current.prev; newNode.next = current; current.prev.next = newNode; current.prev = newNode; size++; } } @Override public T removeFirst() { if (isEmpty()) { throw new NoSuchElementException("List is empty"); } T data = head.data; if (head == tail) { head = tail = null; } else { head = head.next; head.prev = null; } size--; return data; } @Override public T removeLast() { if (isEmpty()) { throw new NoSuchElementException("List is empty"); } T data = tail.data; if (head == tail) { head = tail = null; } else { tail = tail.prev; tail.next = null; } size--; return data; } @Override public T remove(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Invalid index"); } if (index == 0) { return removeFirst(); } else if (index == size - 1) { return removeLast(); } else { Node<T> current = head; for (int i = 0; i < index; i++) { current = current.next; } T data = current.data; current.prev.next = current.next; current.next.prev = current.prev; size--; return data; } } @Override public T getFirst() { if (isEmpty()) { throw new NoSuchElementException("List is empty"); } return head.data; } @Override public T getLast() { if (isEmpty()) { throw new NoSuchElementException("List is empty"); } return tail.data; } @Override public T get(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Invalid index"); } Node<T> current = head; for (int i = 0; i < index; i++) { current = current.next; } return current.data; } @Override public void set(int index, T data) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Invalid index"); } Node<T> current = head; for (int i = 0; i < index; i++) { current = current.next; } current.data = data; } @Override public String toString() { StringBuilder builder = new StringBuilder("["); Node<T> current = head; while (current != null) { builder.append(current.data); if (current.next != null) { builder.append(", "); } current = current.next; } builder.append("]"); return builder.toString(); } } ``` 上述代码实现了LList接口中的所有方法,同时支持双向遍历。需要注意的是,双链表中的每个节点都有一个指向前一个节点的prev指针和一个指向后一个节点的next指针。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值