目录
1. 🔈引言
LinkedList的底层其实就是一个双向链表~
那么什么是双向链表呢?请看下图👇
(从左往右依次为每一个结点)
不难看出:双向链表中每一个结点有三个数据域,分别是data数据、prev前驱、next后继
双向链表的特点:
- 引入了前驱域,解决了单链表只能单向访问的痛点
- 对于双向链表来说,要注意:第一个结点的前驱是null,最后一个结点的后继是null
- 引入一个last,标志尾巴
2. 😊定义双向链表结点
//双向链表结点
class ListNode {
public int data;
public ListNode prev;
public ListNode next;
public ListNode(int data) {
this.data = data;
}
}
public class MyLinkedList {
public ListNode head; //头结点
public ListNode last; //尾结点
}
3. 📰功能列表
//生成链表
public void createList()
//打印链表内容
public void display()
//打印链表长度
public int length()
//查找是否包含关键字key在链表当中
public boolean contains(int key)
//头插法
public void addFirst(int data)
//尾插法
public void addLast(int data)
//找到前一个地址
public Node searchPrev(int index)
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data)
//找关键字key的前驱
public Node searchPrevNode(int key)
//删除第一次出现关键字为key的节点
public void remove(int key)
//删除所有值为key的节点
public void removeAllKey(int key)
//清空链表
public void clear()
5. 💻源代码
MyLinkedList.java
//双向链表结点
class ListNode {
public int data;
public ListNode prev;
public ListNode next;
public ListNode(int data) {
this.data = data;
}
}
public class MyLinkedList {
public ListNode head; //头结点
public ListNode last; //尾结点
//基本功能
//打印链表内容
public void display() {
if (this.head == null) return;
ListNode cur = this.head;
while (cur != null) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
//打印链表长度
public int length() {
ListNode cur = this.head;
int count = 0;
while (cur != null) {
cur = cur.next;
count++;
}
return count;
}
//查找是否包含关键字key在链表当中
public boolean contains(int key) {
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) return true;
cur = cur.next;
}
return false;
}
//插入功能
//头插法
public void addFirst(int data) {
ListNode node = new ListNode(data);
if (this.head == null) {
this.head = node;
this.last = 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.last = node;
} else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
//找到第index的链表头
public ListNode findIndex(int index) {
ListNode cur = this.head;
while (index != 0) {
cur = cur.next;
index--;
}
return cur;
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data) {
if (index < 0 || index > this.length()) throw new RuntimeException("插入位置异常");
if (index == 0) {
this.addFirst(data);
return;
}
if (index == this.length()) {
this.addLast(data);
return;
}
ListNode cur = this.findIndex(index);
ListNode node = new ListNode(data);
node.next = cur;
node.prev = cur.prev;
cur.prev.next = node;
cur.prev = node;
}
//删除第一次出现关键字为key的节点
public void remove(int key) {
if (this.head == null) return;
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) {
//判断是否为头结点
if (cur == this.head) {
this.head = this.head.next;
if (this.head == null) {// 防止只有一个结点
this.last = null;
} else {
this.head.prev = null;
}
} else {
cur.prev.next = cur.next;
// 判断是否为尾结点
if (cur.next == null){
this.last = cur.prev;
} else {
cur.next.prev = cur.prev;
}
}
return;
}else {
cur = cur.next;
}
}
}
//删除所有值为key的节点
public void removeAllKey(int key) {
if (this.head == null) return;
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) {
//判断是否为头结点
if (cur == this.head) {
this.head = this.head.next;
if (this.head == null) {// 防止只有一个结点
this.last = null;
} else {
this.head.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的时候
}else {
cur = cur.next;
}
}
}
//清空链表
public void clear() {
ListNode cur = this.head;
while (cur != null) {
ListNode curNext = cur.next;
cur.prev = null;
cur.next = null;
cur = curNext;
}
this.head = null;
this.last = null;
}
}
test.java
测试代码
public class test {
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addFirst(1);
myLinkedList.addFirst(2);
myLinkedList.addFirst(3);
myLinkedList.addFirst(4);
myLinkedList.addFirst(5);
myLinkedList.addFirst(6);
myLinkedList.display();
System.out.println(myLinkedList.length());
System.out.println(myLinkedList.contains(11));
myLinkedList.addIndex(0,99);
myLinkedList.addIndex(1,59);
myLinkedList.display();
myLinkedList.remove(99);
myLinkedList.display();
}
}