双向链表——Java实现
双向链表
链表是是一种重要的数据结构,有单链表和双向链表之分;本文我将重点阐述不带头结点的双向链表:
不带头结点的带链表
我将对双链表的增加和删除元素操作进行如下解析
1.增加元素(采用尾插法)
(1)链表为空
新建结点,将头结点first和尾节点last都指向新建结点,尾节点的next指向空。
空链表增加元素
(2)链表非空
先定义一个临时的结点temp保存当前的尾节点,将尾节点last指向新建结点,并将last的prev指向temp,temp的next指向last.
非空链表增加元素
2.删除指定下标的元素
我将分以下三种情况进行讨论
(1)要删除元素为头结点
用node保存当前头结点first,并将头结点first指向first.next且将现在的first.prev置为空,将node.的next、data分别置为空。
删除头结点
(2)要删除元素为尾节点
用节点node保存当前的尾节点,将last指向当前尾节点的前一个节点last.prev,并将现last.next置为空,将以前的last即node节点的prev和data置空。
删除尾结点
(3)要删除元素为中间节点
用节点node保存要删除的节点,并将要删除节点的前一个节点的next指向要删除节点的下一个节点;要删除节点的下一个节点的prev指向要删除节点的还是那个一个节点;即node.prev. next = node.next;node.next.prev = node.prev。并将要删除节点的prev、next及data置为null.
删除中间结点
1 package Struct;
2
3 interface Link{
4 void add(Object obj);
5 boolean remove(int index);
6 boolean contain(Object obj);
7 int indexOf(Object obj);
8 boolean set(int index,Object obj);
9 Object get(int index);
10 int length();
11 void clear();
12 Object[] toArray();
13 void printArray(Object[] obj);
14 void printLink();
15 }
16 class Factory{
17 private Factory(){}
18 public static Link getLinkInstance(){
19 return new LinkImpl();
20 }
21 }
22 class LinkImpl implements Link{
23 private Node first;
24 private Node last;
25 private int size;
26 private class Node{
27 private Node prev;
28 private Node next;
29 private Object data;
30 public Node(Object data){
31 this.data = data;
32 }
33 }
34 public void add(Object obj) {
35 //要插入元素为空
36 if(obj == null){
37 return;
38 }
39 Node node = new Node(obj);
40 //空链表
41 if(first == null){
42 first = last = node;
43 first.next = null;
44 size++;
45 }else{
46 //非空链表(尾插)
47 Node temp = this.last;
48 temp.next = node;
49 last = node;
50 last.prev = temp;
51 size++;
52 }
53 }
54 //删除
55 public boolean remove(int index) {
56 //指定下标不合法
57 if(index >= size){
58 return false;
59 }
60 Node node = first;
61 //要删除的节点为头结点
62 if(index == 0){
63 first = node.next;
64 first.prev = null;
65 node.prev = node.next = null;
66 node.data = null;
67 size--;
68 return true;
69 }
70 //要删除节点为尾节点
71 if(index == size-1){
72 Node node1 = last;
73 last = node1.prev;
74 last.next = null;
75 node1.prev = node1.next = null;
76 node1.data = null;
77 size--;
78 return true;
79 }
80 //要删除节点为中间节点
81 Node node3 = get(index);
82 node3.prev.next = node3.next;
83 node3.next.prev = node3.prev;
84 node3.prev = node3.next = null;
85 node3.data = null;
86 size--;
87 return true;
88 }
89 //查看元素是否包含在链表中
90 public boolean contain(Object obj) {
91 //空链表
92 if(first == null&&first.next==null){
93 return false;
94 }
95 for(Node node = first;node!=null;node=node.next){
96 if(node.data==obj){
97 return true;
98 }
99 }
100 return false;
101 }
102 //求取元素obj的下标
103 public int indexOf(Object obj) {
104 Node node = first;
105 int signal = 0;
106 //空链表
107 if(first== null&& first.next == null){
108 return -1;
109 }else{
110 for(node = first;node!=null;node=node.next){
111 if(node.data == obj){
112 return signal;
113 }
114 signal++;
115 }
116 }
117 return signal;
118 }
119 //修改index处的值为obj
120 public boolean set(int index, Object obj) {
121 //指定位置不存在
122 if(index<0||index >= size){
123 return false;
124 }
125 //指定下标超过链表长度
126 if(index >= size){
127 return false;
128 }
129 Node node = first;
130 //若链表头结点是要修改的元素
131 if(node == get(index)){
132 node.data = obj;
133 }
134 Object getObject = get(index);
135 for(node = first;node !=null;node=node.next){
136 if( getObject == node){
137 node.data = obj;
138 }
139 }
140 return true;
141 }
142 //取得index处的元素
143 public Node get(int index) {
144 if(first==null&&first.next==null){
145 return null;
146 }
147 //要查找下标不在范围内
148 if(index >= size){
149 return null;
150 }
151 Node node = first;
152 //要查找元素在中间元素的左侧
153 if(index >=0 && index <= (index<<1)){
154 for(int i = 0;i <= index - 1;i++){
155 if(i == index){
156 return node;
157 }
158 node =node.next;
159 }
160 }
161 else if(index > (index<<1)){
162 //要查找元素在中间元素的右侧
163 for(int i = index; i < size-1;i++){
164 if(i == index){
165 return node;
166 }
167 node = node.next;
168 }
169 }
170 return node;
171 }
172 //求链表长度
173 public int length() {
174 //空链表
175 if(first == null){
176 return 0;
177 }
178 return this.size;
179 }
180 //清空链表
181 public void clear() {
182
183 Node node = first;
184 if(first == null && first.next == null){
185 return;
186 }
187 for(node = first.next;node!=null;){
188 Node temp = node;
189 node.prev = node.next = null;
190 node.data = null;
191 node = node.next;
192 size--;
193 }
194 first.next = null;
195 first.data = null;
196 size--;
197 }
198 //将链表转换成Object数组
199 public Object[] toArray() {
200 //空链表
201 if(first == null && first.next == null){
202 return null;
203 }else{
204 Object[] linkObject = new Object[this.size];//向上转型
205 Node node = first;
206 for(int i = 0;i<size;i++){
207 linkObject[i] = node.data;
208 node = node.next;
209 }
210 return linkObject;
211 }
212 }
213 //打印Object数组
214 public void printArray(Object[] obj){
215 for(int i = 0;i < obj.length;i++){
216 System.out.print(obj[i]+" <-> ");
217 }
218 }
219 //打印链表
220 public void printLink() {
221 Node node = first;
222 for(node = first;node!=null;node=node.next){
223 System.out.print(node.data+" <——> ");
224 }
225 System.out.println();
226 }
227
228 }
229 public class DoubleLinkList {
230 public static void main(String[] args) {
231 Link link = Factory.getLinkInstance();
232 System.out.println("\n"+"=================以下为add测试函数===================");
233 link.add("我是开始位置");
234 link.add("第一名");
235 link.add("第二名");
236 link.add("第三名");
237 link.add("我是结束位置");
238 System.out.println("\n"+"===============以下为printLink测试函数===============");
239 link.printLink();
240 System.out.println("\n"+"===============以下为indexOf测试函数================");
241 System.out.println(link.indexOf("第二名"));
242 System.out.println(link.indexOf("我是结束位置"));
243 System.out.println("\n"+"===============以下为contain测试函数================");
244 System.out.println(link.contain("我是结束位置"));
245 System.out.println(link.contain("hahh"));
246 System.out.println("\n"+"===============以下为get测试函数================");
247 System.out.println(link.get(0));
248 System.out.println(link.get(4));
249 System.out.println(link.get(2));
250 System.out.println(link.get(8));
251 System.out.println("\n"+"===============以下为length测试函数================");
252 System.out.println(link.length());
253 System.out.println("\n"+"===============以下为set测试函数===================");
254 System.out.println(link.set(0, "我是特等奖"));
255 link.printLink();
256 System.out.println("\n"+"===============以下为toArray测试函数===================");
257 Object[] linkObj = link.toArray();
258 System.out.println("\n"+"===============以下为printArray测试函数===================");
259 link.printArray(linkObj);
260 System.out.println("\n"+"===============以下为remove测试函数===================");
261 //删除尾节点
262 System.out.println(link.remove(4));
263 link.printLink();
264 //删除头结点
265 System.out.println(link.remove(0));
266 link.printLink();
267 //删除中间节点
268 System.out.println(link.remove(1));
269 link.printLink();
270 System.out.println(link.length());
271 System.out.println("\n"+"===============以下为clear测试函数===================");
272 link.clear();
273 System.out.println(link.length());
274 }
275 }
测试结果:
双向链表——Java实现的更多相关文章
- 线性链表的双向链表——java实现
.线性表链式存储结构:将采用一组地址的任意的存储单元存放线性表中的数据元素. 链表又可分为: 单链表:每个节点只保留一个引用,该引用指向当前节点的下一个节点,没有引用指向头结点,尾节点的next引用为 ...
- 双向链表--Java实现
/*双向链表特点: *1.每个节点含有两个引用,previos和next,支持向前或向后的遍历(除头节点) *2.缺点插入或删除的时候涉及到引用修改的比较多 *注意:下面的双向链表其实也实现了双端链表 ...
- 双向链表-java完全解析
原文:https://blog.csdn.net/nzfxx/article/details/51728516 "双向链表"-数据结构算法-之通俗易懂,完全解析 1.概念的引入 相 ...
- 剑指Offer:面试题27——二叉搜索树与双向链表(java实现)
问题描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路: 将树分为三部分:左子树,根结点,右子树. 1.我们要把根结点与左 ...
- 双向链表JAVA代码
//双向链表类 publicclassDoubleLinkList{ //结点类 publicclassNode{ publicObject data; ...
- LRU hashMap(拉链) + 双向链表 java实现
//基于 hash (拉链法) + 双向链表,LRUcache //若改为开放寻址,线性探测法能更好使用cpuCache public class LRU { private class Node { ...
- 《剑指offer》面试题27 二叉搜索树与双向链表 Java版
(将BST改成排序的双向链表.) 我的方法一:根据BST的性质,如果我们中序遍历BST,将会得到一个从小到大排序的序列.如果我们将包含这些数字的节点连接起来,就形成了一个链表,形成双向链表也很简单.关 ...
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- JAVA单向/双向链表的实现
一.JAVA单向链表的操作(增加节点.查找节点.删除节点) class Link { // 链表类 class Node { // 保存每一个节点,此处为了方便直接定义成内部类 private Str ...
随机推荐
- 湖湘杯2020 writeup
这个平台中间卡的离谱,卡完过后交了flag分还掉了 Web 题目名字不重要 也算是非预期吧,赛后y1ng师傅也说了因为要多端口环境必须这样配,预期解很难 NewWebsite 后台弱口令admin a ...
- 解读Java8的Thread源码
1.创建的一个无参的Thread对象,默认会有一个线程名,以Thread-开头,从0开始计数,采用了一个static修饰的int变量,当对象初始化一次时一直存放在jvm方法区中 2.构造Thread的 ...
- Github webhooks 自动部署博客文章,使用总结【含视频】
作者:小傅哥 博客:https://bugstack.cn 原文:https://mp.weixin.qq.com/s/VtTHUfyiITNSoGy052jkXQ 沉淀.分享.成长,让自己和他人都能 ...
- win8中让cmd.exe始终以管理员身份运行
最近在学习配置本地服务器,在命令行启动mysql时总是由于权限不足而失败, Win+R -- cmd ,这样总是不能,还要找到cmd.exe右键以管理员身份运行cmd,再 net start mysq ...
- [atARC078F]Mole and Abandoned Mine
注意到最终图的样子可以看作一条从1到$n$的路径,以及删去这条路径上的边后,路径上的每一个点所对应的一个连通块 考虑dp,令$f_{S,i}$表示当前1到$n$路径上的最后一个点以及之前点(包括$i$ ...
- [loj3156]回家路线
令$dp[i]$表示经过第$i$条边后的最小烦躁值,有$且dp[i]=\min_{y_{j}=x_{i}且q_{j}\le p_{i}}dp[j]+f(p_{i}-q_{j})$,其中$f(x)=Ax ...
- [nowcoder5669A]Ancient Distance
对于一个$k$,可以二分枚举答案并判断,判断过程可以贪心找最深的点(线段树区间max)+倍增+线段树区间覆盖(清0)来实现,时间复杂度$o(klog_{2}n)$ 考虑反过来,暴力枚举答案$x$并求出 ...
- FastJson测试用例
基础测试 package com.ai; import com.ai.test.daily.Student; import com.alibaba.fastjson.JSON; import com. ...
- 前台json遍历拼装
//添加角色. $.ajax({ type: "post", url: "/sysRole/list", data: {page: 1, limit: 1000 ...
- Android连接远程数据库的避坑指南
Android连接远程数据库的避坑指南 今天用Android Studio连接数据库时候,写了个测试连接的按钮,然后连接的时候报错了,报错信息: 2021-09-07 22:45:20.433 705 ...