线性表之链式存储结构双向循环链表

双向循环链表:每个结点包含了数据、直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环。可以形象的理解成一群孩子手拉手牵成一个圆圈,从头一个孩子开始可以从左往右报数,也可以从右往左开始报数。

优点:双向循环链表可以迅速的获取当前数据的前驱数据,解决了单向循环链表从头开始遍历的麻烦。

接口类

 1 package list;
 2
 3 public interface Listable<T> {
 4
 5     public void clear();
 6
 7     public boolean isEmpty();
 8
 9     public int Length();
10
11     public T getElement(int index);
12
13     public boolean add(T element);
14
15     public boolean addHead(T element);
16
17     public boolean addByIndex(int index, T element);
18
19     public boolean add(Listable<T> list);
20
21     public T remove(int index);
22
23     public boolean removeAll();
24
25     public T remove(T element);
26
27     public T setElement(int index,T element);
28
29 }

View Code

结点类

 1 //结点类
 2 class Node<T> {
 3     private Node<T> left,right;
 4     private T data;
 5
 6     Node(T data) {
 7         this(data,null,null);
 8     }
 9
10     Node() {
11         this(null,null,null);
12     }
13
14     Node(T data,Node<T> left,Node<T> right) {
15         this.data = data;
16         this.left = left;
17         this.right = right;
18     }
19
20     public T getData() {
21         return this.data;
22     }
23
24     public Node<T> getLeft() {
25         return this.left;
26     }
27
28     public Node<T> getRight() {
29         return this.right;
30     }
31
32     public void setData(T data) {
33         this.data = data;
34     }
35
36     public void setRight(Node<T> right) {
37         this.right = right;
38     }
39
40     public void setLeft(Node<T> left) {
41         this.left = left;
42     }
43
44     public String toString() {
45         return getData().toString();
46     }
47 }

View Code

接口实现类

  1 //接口实现类
  2 class DoubleLinkedList<T> implements Listable<T> {
  3     public Node<T> head;
  4
  5     //建空表,带头结点
  6     DoubleLinkedList() {
  7         this(null);
  8     }
  9
 10     //建表,带头结点,表中有一条数据元素
 11     DoubleLinkedList(T element) {
 12         if(element == null) {
 13             head = new Node<T>(element,null,null);
 14             head.setRight(head);
 15             head.setLeft(head);
 16         }else {
 17             Node<T> headRight = new Node<T>(element,null,null);
 18             head = new Node<T>(null,headRight,headRight);
 19             headRight.setLeft(head);
 20             headRight.setRight(head);
 21         }
 22     }
 23
 24     //清空当前链表
 25     public void clear() {}
 26
 27     //判空表
 28     public boolean isEmpty() {
 29         return head.getRight() == head;
 30     }
 31
 32     //表长
 33     public int Length() {
 34         int len = 0;
 35         Node<T> temp = head;
 36         while(temp.getRight() != head) {
 37             len++;
 38             temp = temp.getRight();
 39         }
 40         return len;
 41     }
 42
 43     //取下标index处的数据
 44     public T getElement(int index) {
 45         if(index <= 0) {
 46             return head.getRight().getData();
 47         }
 48         int len = Length();
 49         if(index >=  len) {
 50             return head.getLeft().getData();
 51         }
 52         T element = null;
 53         if(index > 0 && index < len) {
 54             int k = 0;
 55             Node<T> temp = head;
 56             //此处只能用while不能用if,用错好几次
 57             while(k <= index && temp.getRight() != head) {
 58                 k++;
 59                 temp = temp.getRight();
 60             }
 61             element = temp.getData();
 62         }
 63         return element;
 64     }
 65
 66     //尾添
 67     public boolean add(T element) {
 68         if(element == null) return false;
 69         Node<T> node = new Node<T>(element,head.getLeft(),head);
 70         head.getLeft().setRight(node);
 71         head.setLeft(node);
 72         return true;
 73     }
 74
 75     //首添
 76     public boolean addHead(T element) {
 77         if(element == null) return false;
 78         Node<T> node = new Node<T>(element,head,head.getRight());
 79         head.getRight().setLeft(node);
 80         head.setRight(node);
 81         return false;
 82     }
 83
 84     //表index处,添加新数据element
 85     public boolean addByIndex(int index, T element) {
 86         if(index <= 0) {
 87             return addHead(element);
 88         }else if(index >= Length()) {
 89             return add(element);
 90         }else {
 91             int k = 0;
 92             Node<T> temp = head;
 93             //此处只能用while不能用if,用错好几次
 94             while(k <= index && temp.getRight() != head) {
 95                 k++;
 96                 temp = temp.getRight();
 97             }
 98             Node<T> node = new Node<T>(element,temp.getLeft(),temp);
 99             temp.getLeft().setRight(node);
100             temp.setLeft(node);
101         }
102         return true;
103     }
104
105     //将参数中的链表添加到当前链表的尾部
106     public boolean add(Listable<T> slist) {
107         if(slist.isEmpty() || slist == null) return false;
108         if(slist instanceof DoubleLinkedList) {
109             DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
110             //以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
111             DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
112             for(int i = 0; i < list.Length(); i++) {
113                 temp.add(list.getElement(i));
114             }
115             Node<T> node = temp.head;
116             Node<T> nodeLeft = node.getLeft();
117             Node<T> nodeRight = node.getRight();
118             this.head.getLeft().setRight(node.getRight());
119             nodeRight.setLeft(this.head.getLeft());
120             nodeLeft.setRight(this.head);
121             this.head.setLeft(node.getLeft());
122             return true;
123         }else {
124             return false;
125         }
126     }
127
128     //删除下标Index处的数据
129     public T remove(int index) {
130         if(isEmpty()) return null;
131         if(index < 0) {
132             index = 0;
133         }
134         int len =  Length();
135         if(index >= len) {
136             //当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
137             index = len-1;
138         }
139         T element = null;
140         if(index >= 0 && index < len) {
141             Node<T> temp = head;
142             int k = 0;
143             while(k <= index && temp.getRight() != head) {
144                 k++;
145                 temp = temp.getRight();
146             }
147             element = temp.getData();
148             temp.getRight().setLeft(temp.getLeft());
149             temp.getLeft().setRight(temp.getRight());
150             temp.setRight(null);
151             temp.setLeft(null);
152             temp = null;
153         }
154         return element;
155     }
156
157     //删除当前链表中所有的数据,只剩头结点
158     public boolean removeAll() {
159         if(isEmpty()) return false;
160         Node<T> temp = head.getRight();
161         while(temp != head) {
162             head.setRight(temp.getRight());
163             temp.getRight().setLeft(head);
164             temp.setLeft(null);
165             temp.setRight(null);
166             temp = head.getRight();
167         }
168         return true;
169     }
170
171     //删除链表中从head开始的第一个element数据
172     public T remove(T element) {
173         if(isEmpty() || element == null) return null;
174         //从表中第一个元素开始比较
175         Node<T> temp = head.getRight();
176         int k=0;
177         while(temp != head) {
178             if(element.equals(temp.getData())) {
179                 remove(k);
180                 return element;
181             }else {
182                 temp = temp.getRight();
183                 k++;
184             }
185         }
186         if(k == (Length()-1)) {
187             System.out.println("该链表中没有该数据");
188         }
189         return element;
190     }
191
192     //修改下标index处的数据,并将原始数据返回
193     public T setElement(int index,T element) {
194         if(index < 0 || index >= Length()) return null;
195         Node<T> temp = head;
196         int k = 0;
197         while(k < index && temp.getRight() != head) {
198             k++;
199             temp = temp.getRight();
200         }
201         T tempEle = temp.getData();
202         temp.setData(element);
203         return tempEle;
204     }
205
206     //重写父类toString方法,实际是给list做遍历后将数据打印出来
207     public String toString() {
208         StringBuffer sb = new StringBuffer();
209         /*通过for循环遍历双向循环链表
210         int length = Length();
211         sb.append("[ ");
212         for(int i = 0; i < length; i++) {
213             sb.append(getElement(i)+" ");
214         }
215         sb.append("]");
216         */
217         //从表头开始遍历双向循环链表
218         sb.append("[ ");
219         Node<T> node = head;
220         while(node.getRight() != head) {
221             sb.append(node.getRight().getData()+" ");
222             node = node.getRight();
223         }
224         sb.append("]");
225         return sb.toString();
226     }
227
228 }

View Code

测试类

 1 package list;
 2
 3 //************************************************
 4 //*双向循环链表-java实现(画图分析会容易理解得多)
 5 //************************************************
 6
 7 public class TestDoubleLinkedList {
 8     public static void main(String[] args) {
 9         Listable<String> list = new DoubleLinkedList<String>("a");
10         list.add("b");
11         list.add("c");
12         list.addByIndex(3,"e");
13         list.addByIndex(3,"d");
14         list.addByIndex(5,"f");
15         System.out.println(list);
16         list.addHead("A");
17         System.out.println(list.Length());
18         System.out.println(list);
19         Listable<String> list1 = new DoubleLinkedList<String>("123456");
20         list.add(list1);
21         System.out.println(list);
22         list.remove(100);
23         list.add("123456");
24         System.out.println("list="+list);
25         System.out.println(list1);
26         list1.removeAll();
27         System.out.println(list1+"  list1 is Empty??"+list1.isEmpty());
28         list.remove("123456");
29         System.out.println("list="+list);
30         System.out.println("remove item="+list.remove("A"));
31         System.out.println("list="+list);
32     }
33 }

View Code

完整代码

  1 package list;
  2
  3 //************************************************
  4 //*双向循环链表-java实现(画图分析会容易理解得多)
  5 //************************************************
  6
  7 public class TestDoubleLinkedList {
  8     public static void main(String[] args) {
  9         Listable<String> list = new DoubleLinkedList<String>("a");
 10         list.add("b");
 11         list.add("c");
 12         list.addByIndex(3,"e");
 13         list.addByIndex(3,"d");
 14         list.addByIndex(5,"f");
 15         System.out.println(list);
 16         list.addHead("A");
 17         System.out.println(list.Length());
 18         System.out.println(list);
 19         Listable<String> list1 = new DoubleLinkedList<String>("123456");
 20         list.add(list1);
 21         System.out.println(list);
 22         list.remove(100);
 23         list.add("123456");
 24         System.out.println("list="+list);
 25         System.out.println(list1);
 26         list1.removeAll();
 27         System.out.println(list1+"  list1 is Empty??"+list1.isEmpty());
 28         list.remove("123456");
 29         System.out.println("list="+list);
 30         System.out.println("remove item="+list.remove("A"));
 31         System.out.println("list="+list);
 32     }
 33 }
 34
 35 //结点类
 36 class Node<T> {
 37     private Node<T> left,right;
 38     private T data;
 39
 40     Node(T data) {
 41         this(data,null,null);
 42     }
 43
 44     Node() {
 45         this(null,null,null);
 46     }
 47
 48     Node(T data,Node<T> left,Node<T> right) {
 49         this.data = data;
 50         this.left = left;
 51         this.right = right;
 52     }
 53
 54     public T getData() {
 55         return this.data;
 56     }
 57
 58     public Node<T> getLeft() {
 59         return this.left;
 60     }
 61
 62     public Node<T> getRight() {
 63         return this.right;
 64     }
 65
 66     public void setData(T data) {
 67         this.data = data;
 68     }
 69
 70     public void setRight(Node<T> right) {
 71         this.right = right;
 72     }
 73
 74     public void setLeft(Node<T> left) {
 75         this.left = left;
 76     }
 77
 78     public String toString() {
 79         return getData().toString();
 80     }
 81 }
 82
 83 //接口实现类
 84 class DoubleLinkedList<T> implements Listable<T> {
 85     public Node<T> head;
 86
 87     //建空表,带头结点
 88     DoubleLinkedList() {
 89         this(null);
 90     }
 91
 92     //建表,带头结点,表中有一条数据元素
 93     DoubleLinkedList(T element) {
 94         if(element == null) {
 95             head = new Node<T>(element,null,null);
 96             head.setRight(head);
 97             head.setLeft(head);
 98         }else {
 99             Node<T> headRight = new Node<T>(element,null,null);
100             head = new Node<T>(null,headRight,headRight);
101             headRight.setLeft(head);
102             headRight.setRight(head);
103         }
104     }
105
106     //清空当前链表
107     public void clear() {}
108
109     //判空表
110     public boolean isEmpty() {
111         return head.getRight() == head;
112     }
113
114     //表长
115     public int Length() {
116         int len = 0;
117         Node<T> temp = head;
118         while(temp.getRight() != head) {
119             len++;
120             temp = temp.getRight();
121         }
122         return len;
123     }
124
125     //取下标index处的数据
126     public T getElement(int index) {
127         if(index <= 0) {
128             return head.getRight().getData();
129         }
130         int len = Length();
131         if(index >=  len) {
132             return head.getLeft().getData();
133         }
134         T element = null;
135         if(index > 0 && index < len) {
136             int k = 0;
137             Node<T> temp = head;
138             //此处只能用while不能用if,用错好几次
139             while(k <= index && temp.getRight() != head) {
140                 k++;
141                 temp = temp.getRight();
142             }
143             element = temp.getData();
144         }
145         return element;
146     }
147
148     //尾添
149     public boolean add(T element) {
150         if(element == null) return false;
151         Node<T> node = new Node<T>(element,head.getLeft(),head);
152         head.getLeft().setRight(node);
153         head.setLeft(node);
154         return true;
155     }
156
157     //首添
158     public boolean addHead(T element) {
159         if(element == null) return false;
160         Node<T> node = new Node<T>(element,head,head.getRight());
161         head.getRight().setLeft(node);
162         head.setRight(node);
163         return false;
164     }
165
166     //表index处,添加新数据element
167     public boolean addByIndex(int index, T element) {
168         if(index <= 0) {
169             return addHead(element);
170         }else if(index >= Length()) {
171             return add(element);
172         }else {
173             int k = 0;
174             Node<T> temp = head;
175             //此处只能用while不能用if,用错好几次
176             while(k <= index && temp.getRight() != head) {
177                 k++;
178                 temp = temp.getRight();
179             }
180             Node<T> node = new Node<T>(element,temp.getLeft(),temp);
181             temp.getLeft().setRight(node);
182             temp.setLeft(node);
183         }
184         return true;
185     }
186
187     //将参数中的链表添加到当前链表的尾部
188     public boolean add(Listable<T> slist) {
189         if(slist.isEmpty() || slist == null) return false;
190         if(slist instanceof DoubleLinkedList) {
191             DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
192             //以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
193             DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
194             for(int i = 0; i < list.Length(); i++) {
195                 temp.add(list.getElement(i));
196             }
197             Node<T> node = temp.head;
198             Node<T> nodeLeft = node.getLeft();
199             Node<T> nodeRight = node.getRight();
200             this.head.getLeft().setRight(node.getRight());
201             nodeRight.setLeft(this.head.getLeft());
202             nodeLeft.setRight(this.head);
203             this.head.setLeft(node.getLeft());
204             return true;
205         }else {
206             return false;
207         }
208     }
209
210     //删除下标Index处的数据
211     public T remove(int index) {
212         if(isEmpty()) return null;
213         if(index < 0) {
214             index = 0;
215         }
216         int len =  Length();
217         if(index >= len) {
218             //当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
219             index = len-1;
220         }
221         T element = null;
222         if(index >= 0 && index < len) {
223             Node<T> temp = head;
224             int k = 0;
225             while(k <= index && temp.getRight() != head) {
226                 k++;
227                 temp = temp.getRight();
228             }
229             element = temp.getData();
230             temp.getRight().setLeft(temp.getLeft());
231             temp.getLeft().setRight(temp.getRight());
232             temp.setRight(null);
233             temp.setLeft(null);
234             temp = null;
235         }
236         return element;
237     }
238
239     //删除当前链表中所有的数据,只剩头结点
240     public boolean removeAll() {
241         if(isEmpty()) return false;
242         Node<T> temp = head.getRight();
243         while(temp != head) {
244             head.setRight(temp.getRight());
245             temp.getRight().setLeft(head);
246             temp.setLeft(null);
247             temp.setRight(null);
248             temp = head.getRight();
249         }
250         return true;
251     }
252
253     //删除链表中从head开始的第一个element数据
254     public T remove(T element) {
255         if(isEmpty() || element == null) return null;
256         //从表中第一个元素开始比较
257         Node<T> temp = head.getRight();
258         int k=0;
259         while(temp != head) {
260             if(element.equals(temp.getData())) {
261                 remove(k);
262                 return element;
263             }else {
264                 temp = temp.getRight();
265                 k++;
266             }
267         }
268         if(k == (Length()-1)) {
269             System.out.println("该链表中没有该数据");
270         }
271         return element;
272     }
273
274     //修改下标index处的数据,并将原始数据返回
275     public T setElement(int index,T element) {
276         if(index < 0 || index >= Length()) return null;
277         Node<T> temp = head;
278         int k = 0;
279         while(k < index && temp.getRight() != head) {
280             k++;
281             temp = temp.getRight();
282         }
283         T tempEle = temp.getData();
284         temp.setData(element);
285         return tempEle;
286     }
287
288     //重写父类toString方法,实际是给list做遍历后将数据打印出来
289     public String toString() {
290         StringBuffer sb = new StringBuffer();
291         /*通过for循环遍历双向循环链表
292         int length = Length();
293         sb.append("[ ");
294         for(int i = 0; i < length; i++) {
295             sb.append(getElement(i)+" ");
296         }
297         sb.append("]");
298         */
299         //从表头开始遍历双向循环链表
300         sb.append("[ ");
301         Node<T> node = head;
302         while(node.getRight() != head) {
303             sb.append(node.getRight().getData()+" ");
304             node = node.getRight();
305         }
306         sb.append("]");
307         return sb.toString();
308     }
309
310 }

View Code

后期会添加两个链表求交集等操作。

转载于:https://www.cnblogs.com/nora-xie/p/3352909.html

java与数据结构(4)---java实现双向循环链表相关推荐

  1. 数据结构(三)---双向循环链表的实现---java版

    节点设置 package com.cn.hbut.domain; /**  * @author Administrator  * 双向循环链表的节点设置  */ public class DNode ...

  2. 数据结构与算法 | 带头双向循环链表

    上一节里实现的是最简单的链表,在实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等.而比较常用的就是带头双向循环链表. 通过对比我们可以看出有三个不同,多了头节点,链表 ...

  3. 【数据结构】-关于带头双向循环链表的增删查改

    作者:低调 作者宣言:写好每一篇博客 文章目录 前言 一.带头双向循环链表的实现 1.1创建返回链表的头结点 1.2开辟一个新的结点 1.3双向链表的销毁 1.4双向链表的打印 1.5双向链表尾插 1 ...

  4. 【数据结构】带头节点双向循环链表

    目录 顺序表和链表的区别 带头双向循环链表分析 带头双向循环链表结构: 创建一个节点 哨兵位头节点 打印链表中的值 在pos前插入 删除pos位置的节点 尾插 尾删 头插: 头删 链表元素查找 总代码 ...

  5. 比特数据结构与算法(第二章收尾)带头双向循环链表的实现

    1.链表的分类 链表的分类 ① 单向或者双向 ② 带头或者不带头 ③ 循环或者非循环 常用的链表: 根据上面的分类我们可以细分出8种不同类型的链表,这么多链表我们一个个讲解这并没有意义.我们实际中最常 ...

  6. java 双向链表循环_双向循环链表的Java版本实现

    1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...

  7. java循环单链表类构造函数_C++实现双向循环链表

    本文实例为大家分享了C++实现双向循环链表的具体代码,供大家参考,具体内容如下 一.概念 1.在双链表中的每个结点应有两个链接指针: lLink -> 指向前驱结点  (前驱指针或者左链指针) ...

  8. Java常见数据结构以及特点、使用场景

    Java常见数据结构以及特点 Java中常见的数据结构,主要分为Collection和Map两种主要接口,程序中的数据结构是继承这些接口的数据结构类. Collection接口: List 接口继承: ...

  9. java链表实现_数据结构——基于java的链表实现(真正理解链表这种数据结构)...

    一.链表介绍 1.什么是链表? 链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.如下图所示,在数据结构中,a1里面的指针存储着a2的地址,这样一个 ...

最新文章

  1. Python 3.10的几个好用的新特性
  2. jquery下拉分页
  3. Webservice入门教程_编写天气预报的webservice
  4. 上传文件、上传按钮、Form组件上传文件
  5. opencv4.4.0函数手册_Cobalt strike3.0使用手册
  6. Linux服务-telnet服务部署(配置允许root登录)
  7. linux如何自动调jiaob,最牛B的 Linux Shell 命令 系列连载(四)
  8. Comparable接口的使用:(知识回顾)
  9. 不知道不 OK!53 个 Python 经典面试题详解
  10. 马化腾回应《腾讯没有梦想》:我的理想不是赚多少钱
  11. 开源小工具 酷狗、网易音乐缓存文件转mp3工具
  12. Selenium webdriver实现原理
  13. Java调用so文件
  14. 医学自然语言处理(NLP)相关论文汇总之 NAACL 2022
  15. office表格怎么冻结前两行_冻结Excel表格中多行或多列的方法
  16. MobaXterm复制黏贴快捷键
  17. 应用特征值矩阵对角方法
  18. 亚马逊将为语音助手研发AI芯片 欲追赶苹果
  19. 少年派的计算机游戏怎么弄,少年派的无聊之旅攻略大全图文详解
  20. pandas学习笔记1—categories与set_categories

热门文章

  1. 菜鸟程序员的成长之路-工作篇
  2. Firefox 在后台打开标签:about:config
  3. 离线轻量级大数据平台Spark之MLib机器学习库TF-IDF实例
  4. 模糊数学笔记:五、模糊聚类
  5. 小程序中textarea层级最高的结局办法
  6. 转载:sqlmap的应用实战
  7. 关于Icon,Image,ImageIcon的简单的对比参考
  8. leetcode C++ 6. Z 字形变换 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
  9. 流水灯实例,点亮发光管LED并闪烁(查表操作)
  10. 【BLE】TLSR8258开发记录之12--手机扫描蓝牙显示中文