双向链表问题
1.双向链表的定义
//节点的定义,一个节点有三个域
class Node {
public int data;
public Node next;
public Node prev;
//不带参数的构造函数
public Node () {
}
//带一个参数的构造函数
public Node (int data) {
this.data = data;
}
}
class DoubleLinklist {
public Node head;
public Node last;
public DoubleLinklist() {
this.head = null;
this.last = null;
}
//在此实现单链表的插入、删除等方法
}
2.双向链表的头插法
头插法:(两种情况)链表为空和链表不为空
//头插法:
//两种情况:链表为空和链表不为空
public void addFirst(int data) {
Node node = new Node(data);
if (this.head == null) {
this.head = node;
this.last = node;
} else {
node.next = this.head;
node.next.prev = node;
this.head = node;
}
}
3.双向链表的尾插法
尾插法:
链表为空,则和头插法链表为空一致
链表不为空,让新插入节点变为last
public void addLast(int data) {
Node node = new Node(data);
if (head == null) {
this.head = node;
this.last = node;
} else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
4.插入指定位置index
插入指定位置index:
在下标合法的前提下,index为0,则头插,index等于长度,则尾插;
双向链表记录前趋,这里直接找到index位置插入;
先绑插入节点node的东西,再绑后继的东西,再绑前趋的东西。
public boolean addIndex(int index,int data) {
checkIndex(index);
if (index == 0) {
addFirst(data);
return true;
}
if (index == getSize()) {
addLast(data);
return true;
}
Node node = new Node(data);
Node cur = searchIndex(index);
node.next = cur;
node.prev = cur.prev;
cur.prev = node;
node.prev.next = node;
return true;
}
// 获取双向链表的长度
public int getSize() {
Node cur = this.head;
int count = 0;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
//检查下标合法性
private void checkIndex( int index) {
if(index <0 || index > getSize()){
throw new IndexOutOfBoundsException("下标不合法");
}
}
//查找index位置
private Node searchIndex(int index) {
int count = 0;
Node cur = this.head;
while (count < index ){
cur = cur.next;
count++;
}
return cur;
}
5.查找是否包含某个关键字为key的节点
//查找是够包含某个关键字key
public boolean contains(int key) {
Node cur = this.head;
while(cur != null){
if(cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
6.删除第一次出现关键字为key的节点
删除第一次出现的关键字为key 的节点:
分为删的头节点和不是头节点
不是头节点的情况中包含了是尾节点
public int remove(int key) {
Node cur = this.head;
int oldData = -1;//用来存储删除的值
while(cur != null) {
if(cur.data == key) {
oldData = cur.data;
if(cur == this.head) {
this.head = cur.next;
this.head.prev = null;
}else {
if(cur.next != null){
cur.next.prev = cur.prev;
} else {
this.last = cur.prev;
}
cur.prev.next = cur.next;
}
return oldData;
}
cur = cur.next;
}
return oldData;
}
7.删除所有值为key的节点
删除所有值为key的节点:与删除第一次出现的关键字key类似,只不过加上循环,从头到尾遍历链表
public void removeAllKey(int key) {
Node cur = this.head;
while(cur != null){
if(cur.data == key){
if(cur == this.head){
this.head = cur.next;
if(this.head != null)
this.head.prev = null;
}else {
if(cur.next != null) {
cur.next.prev = cur.prev;
}else {
this.last = cur.prev;
}
cur.prev.next = cur.next;
}
}
cur = cur.next;
}
}
8.双向链表的打印
//打印双向链表
public void display() {
Node cur = this.head;
while(cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
9.双向链表的清空
清空双向链表: 清空时需要注意一个节点由两个节点引用,也就是一个节点prev、next各引用了一个节点; 所以要将节点的next和prev 都置为null,head,last 也都引用,也要置空。
public void clear() {
Node cur = this.head;
while(cur != null){
Node curNext = cur.next;
cur.next = null;
cur.prev = null;
cur = curNext;
}
this.head = null;
this.last = null;
}