1.双向链表:此链表中有两条方向不同的链。
此链表的每个节点包括三个域:
(1)数据域:存储节点的值
(2)前驱指针域prev:指向其前驱
(3)后继指针域next:存储数据元素的直接后继的地址(或位置)
2.模拟实现:
首先创建一个DoubeLinkedList类:
class ListNode {
private int data;
private ListNode next;
private ListNode prev;
public ListNode(){
}
public ListNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public ListNode getNext() {
return next;
}
public void setNext(ListNode next) {
this.next = next;
}
public ListNode getPrev() {
return prev;
}
public void setPrev(ListNode prev) {
this.prev = prev;
}
}
定义双向链表的头结点和尾结点
public class DoubleLinkedList {
private ListNode head;//头
private ListNode last;//定义尾结点
}
1.头插法:
//1.头插法
public void addFirst(int data) {
//创建节点
ListNode node = new ListNode(data);
if(this.head == null){
this.head = node;
this.last = node;
}else{
node.setNext(this.head);
this.head.setPrev(node);
this.head = node;
}
}
2.尾插法:
//2.尾插法
public void addLast(int data) {
ListNode node = new ListNode(data);
if(this.head == null){
this.head = node;
this.last = node;
}else{
last.setNext(node);
node.setPrev(this.head);
last = node;
}
}
3.打印链表:
//3.打印链表
public void display() {
ListNode cur = this.head;
while(cur != null){
System.out.print(cur.getData() + " ");
cur = cur.getNext();
}
System.out.println();
}
4.查找是否包含关键字key是否在单链表当中
//4.查找是否包含关键字key是否在单链表当中
public boolean contains(int key) {
ListNode cur = this.head;
while(cur != null){
if(cur.getData() == key){
return true;
}
cur = cur.getNext();
}
return false;
}
5.删除第一次出现关键字为key的节点
方法1:
//5.删除第一次出现关键字为key的节点
public void remove1(int key) {
ListNode cur = this.findNode(key);
if(cur == null) {
return;
}
//即找到了key,对其进行删除
if(cur == this.head) {//若key为头结点
this.head = this.head.getNext();
//this.head.prev = null;
this.head.setPrev(null);
return;
}
if(cur == this.last) {//若key为尾结点
cur.getPrev().setNext(null);
this.last = this.last.getPrev();
return;
}
//其余节点删除
cur.getPrev().setNext(cur.getNext());
cur.getNext().setPrev(cur.getPrev());
}
public ListNode findNode(int key) {//寻找删除key所在的节点,key节点可能不存在。
ListNode cur = this.head;
while (cur != null) {
if(cur.getData() == key) {
return cur;
}
cur = cur.getNext();
}
return null;
}
方法2:
public void remove2(int key) {
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) {
if(cur == this.head) {
//头结点
this.head = this.head.next;
this.head.prev = null;
}else {
cur.prev.next = cur.next;
if(cur.next != null) {
cur.next.prev = cur.prev;
}else {
//cur.next == null
this.last = this.last.prev;
}
}
return;
}
cur = cur.next;
}
}
6.删除所有值为key的节点
方法1:
//6.删除所有值为key的节点
public void removeAllKey1(int key) {
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) {
if(cur == this.head) {
//头结点
this.head = this.head.next;
this.head.prev = null;
}else {
cur.prev.next = cur.next;
if(cur.next != null) {
cur.next.prev = cur.prev;
}else {
//cur.next == null
this.last = this.last.prev;
}
}
}
cur = cur.next;
}
}
方法2:
public void removeAllKey2(int key) {
ListNode cur = this.head;
while (cur != null) {
if(cur.data == key) {
if(cur == this.head) {
this.head = this.head.next;
this.head.prev = null;
}else if(cur == this.last) {
cur.prev.next = null;
this.last = this.last.prev;
}else {
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
}
//return;
}
cur = cur.next;
}
}
7.得到单链表的长度
//7.得到单链表的长度
public int size() {
ListNode cur = this.head;
int count = 0;
while(cur != null){
count++;
cur = cur.getNext();
}
return count;
}
8.任意位置插入,第一个数据节点为0号下标
//8.任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data) {
//判断index的合法性
if(index < 0 || index > size()) {
return;
}
if(index == 0) {//头插法
addFirst(data);
return;
}
if(index == size()) {//尾插法
addLast(data);
return;
}
ListNode cur = this.head;
while (index != 0) {
//cur = cur.next;
cur = cur.getNext();
index--;
}
ListNode node = new ListNode(data);
//node.next = cur;
node.setNext(cur);
//node.prev = cur.prev;
node.setPrev(cur.getPrev());
//node.prev.next = node;
node.getPrev().setNext(node);
//cur.prev = node;
cur.setPrev(node);
}
9.清空链表
//9.清空链表
public void clear() {
this.head.setNext(null);
this.last.setNext(null);
}