Java实现一个双向链表
定义一个ListNode类,来定义一个双向链表的节点
class ListNode {
public int val;
public ListNode prev;//节点的前驱
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
定义一个MyDoubleList类,在类中实现以下函数
public class MyDoubleList {
public ListNode head;//头
public ListNode tail;//尾巴
}
头插法
public void addFirst(int data) {
ListNode node = new ListNode(data);
//第一次插入
if (this.head == null){
this.head = node;
this.tail = node;
}else {
node.next = this.head;
this.head.prev = node;
this.head = node;
}
}
尾插法
public void addLast(int data) {
ListNode node = new ListNode(data);
//第一次插入
if(this.head == null){
this.head = node;
this.tail = node;
}else {
this.tail.next = node;
node.prev = this.tail;
this.tail = node;
}
}
任意位置插入,第一个数据节点为0号下标
先定义一个函数查找index的位置
public ListNode findIndex(int index){
ListNode cur = this.head;
int count = 0;
while (count != index){
cur = cur.next;
count++;
}
return cur;
}
public void addIndex(int index,int data){
//判断index位置合法性
if (index < 0 || index > size()){
System.out.println("index位置不合法");
return ;
}
//头插
if (index == 0){
addFirst(data);
return ;
}
//尾插
if (index == size()){
addLast(data);
return;
}
//中间插
ListNode cur = findIndex(index);
ListNode node = new ListNode(data);
node.next = cur;
cur.prev.next = node;
node.prev = cur.prev;
cur.prev = node;
}
查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = this.head;
while (cur != null){
if (cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
删除第一次出现关键字为key的节点
public void remove(int key){
ListNode cur = this.head;
while (cur != null){
if (cur.val == key){
//删除头
if (this.head.val == key){
this.head = this.head.next;
if (this.head != null){
//链表只有一个节点并且这个节点是要被删除的
this.head.prev = null;
}else {
this.tail = null;
}
}else {
//删除中间
if (cur.next != null){
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}else {//删除尾
cur.prev.next = cur.next;
tail = cur.prev;
}
}
return;//找到就跳出程序
}else {
cur = cur.next;
}
}
}
删除所有值为key的节点
public void removeAllKey(int key){
ListNode cur = this.head;
while (cur != null){
if (cur.val == key){
//删除头
if (this.head.val == key){
this.head = this.head.next;
if (this.head != null){
//链表只有一个节点并且这个节点是要被删除的
this.head.prev = null;
}else {
this.tail = null;
}
}else {
//删除中间
if (cur.next != null){
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}else {//删除尾
cur.prev.next = cur.next;
tail = cur.prev;
}
}
}
cur = cur.next;//找到也没有跳出程序,直到遍历完整个链表
}
}
得到单链表的长度
public int size(){
ListNode cur = this.head;
int count = 0;
while (cur != null){
cur = cur.next;
count++;
}
return count;
}
打印
public void display(){
ListNode cur = this.head;
while (cur != null){
System.out.print(cur.val+" ");
cur = cur.next;
}
System.out.println();
}
清除
如果直接将头和尾都置为null,则只有头和尾不被引用,链表中其他的节点依旧在被引用,会造成内存泄漏
public void clear(){
//this.head = null;
//this.tail = null;
ListNode cur = this.head;
while (cur != null){
ListNode curNext = cur.next;
cur.next = null;
cur.prev = null;
cur = curNext;
}
this.head = null;
this.tail = null;
}
实现这个双向链表
建立一个测试类,来测试这些函数的输出
public class TestDemo {
public static void main(String[] args) {
MyDoubleList myDoubleList = new MyDoubleList();
//头插法
myDoubleList.addFirst(4);
myDoubleList.addFirst(3);
myDoubleList.addFirst(2);
myDoubleList.addFirst(2);
//尾插法
myDoubleList.addLast(5);
myDoubleList.addLast(6);
myDoubleList.addLast(7);
myDoubleList.addLast(8);
//打印
myDoubleList.display();
//在6号位置插入10
myDoubleList.addIndex(6,10);
//打印
myDoubleList.display();
//查找链表中有没有-1这个值
System.out.println(myDoubleList.contains(-1));
//删除链表中的3
myDoubleList.remove(3);
//打印
myDoubleList.display();
//删除链表中所有的2
myDoubleList.removeAllKey(2);
//打印
myDoubleList.display();
//打印链表的长度
System.out.println(myDoubleList.size());
System.out.println("清除");
//清除链表
myDoubleList.clear();
//打印
myDoubleList.display();
得到结果: