java学习|实现双向链表(带傀儡节点)
引言 【java学习|实现双向链表(带傀儡节点)】在之前的博文中,我简单的向大家分享了一些链表相关的知识及一些面试题,如果感兴趣的老铁可以去瞧瞧,今天做题遇到要实现带傀儡节点的双向链表,做了下,之前的单向链表中我们也遇到要设置傀儡节点(哨兵节点的题),今天我们就来看一下实现双向链表(带傀儡节点)。
基本思路 **对于链表没说带傀儡节点或者虚拟节点,这个链表没有真正的头结点,但是我们把第一个节点叫做头结点,它起到标识的作用,标识这个链表的头结点
这个头结点的位置随时可能发生这变化,是不固定的,之后通过这个头结点我们要完成一些链表的增删查改。如果带傀儡节点这个节点的位置是固定的,那么以后我们操作链表就以这个傀儡节点作为头结点,完成我们的一些基本的增删查改操作。**这就很简单了,具体思路见我之前双链表的博文。
代码如下内有关键注释:
DoubleLinkedList .java
///实现双向链表(带傀儡节点)代码
class ListNode {public int data;
public ListNode prev;
public ListNode next;
public ListNode(int data) {this.data = https://www.it610.com/article/data;
}
}
public class DoubleLinkedList {public ListNode dummyHead;
//虚拟头结点
public ListNode last;
//尾结点
public DoubleLinkedList() {this.dummyHead = new ListNode(-1);
//傀儡节点
}//找到某一位置的节点,用于删除节点
public ListNode findIndex(int index) {ListNode cur = dummyHead.next;
while (index != 0) {cur = cur.next;
index--;
}
return cur;
}//头插法
public void addFirst(int data) {ListNode node=new ListNode(data);
//第一次插入一个节点也没有时的情况
if(this.dummyHead.next==null) {node.prev=this.dummyHead;
this.dummyHead.next=node;
this.last=node;
return;
// this.head=node;
//带头了就不用再定义头了
}else {//新插入的节点和他前后的节点连接
node.next=this.dummyHead.next;
node.prev=this.dummyHead;
this.dummyHead.next.prev=node;
this.dummyHead.next=node;
}
}//尾插法
public void addLast(int data) {ListNode node=new ListNode(data);
if(this.dummyHead.next==null&&this.last==null) {node.prev=this.dummyHead;
this.dummyHead.next=node;
this.last=node;
return;
}else {this.last.next=node;
node.prev=this.last;
this.last=node;
}
}//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index, int data) {//判断位置的合法性,任意位置插入,第一个数据节点为0号下标
if (index < 0 || index> size()) {System.out.println("输入的位置不合法");
return;
} else {if (index == 0) {addFirst(data);
return;
}
if (index == size()) {addLast(data);
}else {//中间插
ListNode node = new ListNode(data);
ListNode cur;
cur = findIndex(index);
cur.prev.next = node;
//当index==size时,如果不采用尾插法,会出现空指针异常
node.prev = cur.prev;
cur.prev = node;
node.next = cur;
}
}}//查找是否包含关键字key是否在单链表当中
public boolean contains(int key) {ListNode cur = this.dummyHead.next;
while (cur != null) {if (cur.data =https://www.it610.com/article/= key) return true;
cur=cur.next;
}
//return false;
return false;
}//删除第一次出现关键字为key的节点
public void remove(int key) {ListNode cur = this.dummyHead.next;
while(cur != null) {if(cur.data == key) {if(cur == this.dummyHead.next) {//头结点是唯一的一个节点或不是唯一的一个节点的情况是一样的,
// 都是下面的代码和之前的不带头结点的双向链表不同
this.dummyHead.next = this.dummyHead.next.next;
//两步代码是前后承接的
this.dummyHead.next.prev = this.dummyHead;
} else {cur.prev.next = cur.next;
//判断是不是最后一个节点
//要删除的节点不是最后一个节点
if (cur.next != null) {cur.next.prev = cur.prev;
} else {//要删除的节点是最后一个节点
this.last = cur.prev;
}
}
return;
} else {cur = cur.next;
}
}
}//删除所有值为key的节点
public void removeAllKey(int key) {ListNode cur = dummyHead.next;
while (cur != null) {//
if (cur.data == key) {//判断是不是头结点
if (cur == this.dummyHead.next) {
//注意这里不要出错
this.dummyHead.next=this.dummyHead.next.next;
this.dummyHead.next.prev=null;
} else {cur.prev.next = cur.next;
//判断是不是最后一个节点
if (cur.next == null) {this.last = cur.prev;
} else {cur.next.prev = cur.prev;
}}}
cur = cur.next;
继续往后走不要停 直到为null 的时候
}
}//得到单链表的长度
public int size() {ListNode cur =this.dummyHead.next;
int count = 0;
while (cur != null) {count++;
cur = cur.next;
}
return count;
}public void display() {ListNode cur = this.dummyHead.next;
while (cur != null) {System.out.print(cur.data +" ");
cur = cur.next;
}
System.out.println();
}public void clear() {//把所有的节点都置为null
ListNode cur =this.dummyHead.next;
ListNode curNext;
while (cur != null) {curNext = cur.next;
cur.prev = null;
cur.next = null;
cur = curNext;
}
this.dummyHead = null;
this.last = null;
}
}
测试类
ublic class TestDemo {public static void main(String[] args) {DoubleLinkedList doubleLinkedList =new DoubleLinkedList();
doubleLinkedList.addFirst(1);
doubleLinkedList.addFirst(2);
doubleLinkedList.addFirst(3);
doubleLinkedList.addFirst(0);
System.out.println(doubleLinkedList.size());
doubleLinkedList.display();
System.out.println(doubleLinkedList.contains(0));
System.out.println("======================================");
doubleLinkedList.removeAllKey(1);
doubleLinkedList.display();
doubleLinkedList.addFirst(0);
doubleLinkedList.display();
}
}
?过小??如果9??以话记点持,
往期文章:
双向链表的实现(双向链表与单向链表的简单区别联系和实现)
链表的概念和结构及基本功能函数的实现(单链表的实现)
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 事件代理
- 孩子不是实现父母欲望的工具——林哈夫
- 一起来学习C语言的字符串转换函数
- opencv|opencv C++模板匹配的简单实现