Java中双向链表的基础功能实现
首先定义节点,双向链表和单向链表相比多了 前区部分:用来记录往回走的节点位置;
/**
* 定义双向链表的实体类
*/
class Node {
public int data;
public Node next;
public Node prev;
public Node(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
在定义了双向链表节点属性后,就可以对其插入,删除,添加,打印等函数进行编写,整体类文件如下:
package demo0720;
public class DoubleLink {
public Node head;//标志双向链表的头
public Node tail;//标志双向链表的尾
/**
* 定义双向链表的实体类
*/
class Node {
public int data;
public Node next;
public Node prev;
public Node(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
/**
* 头插法 在插入的时候就讲 头和尾用head 和 tail进行了标记;
* 后续任何想要使用头和尾的时候 ,都可以直接用这两个标记来操作;
*/
public void addFirst(int data) {
Node node = new Node(data);
if (head == null) {
head = node;
tail = node;
} else {
node.next = head;
head.prev = node;
head = node;
}
}
/**
* 尾插法
*/
public void addLast(int data) {
Node node = new Node(data);
Node cur = this.head;
if (this.head == null && this.tail == null) {
this.head = node;
this.tail = node;
return;
} else {
tail.next = node;
node.prev = tail;
tail = node;
}
}
/**
* 在任意位置index 插入元素
*/
public void addIndex(int index, int data) {
Node cur = this.head;
Node node = new Node(data);
if (index < 0 && index > size()) {
System.out.println("pos位置不合法!");
return;
} else {
if (index == 0) {
addFirst(data);
return;
}
if (index == size()) {
addLast(data);
return;
}
for (int i = 0; i < index - 1; i++) {
cur = cur.next;
}
node.next = cur.next;
cur.next = node;
}
}
/**
* 使用双链表性质 在任意pos位置插入元素
*/
public void addPos(int pos, int data) {
Node node = new Node(data);
Node cur = this.head;
if (pos >= 0 && pos <= size()) {
if (pos == 0) {
addFirst(data);
return;
}
if (pos == size()) {
addLast(data);
return;
}
while (pos != 0) {
cur = cur.next;
pos--;
}
node.next = cur;
node.prev = cur.prev;
cur.prev.next = node;
cur.prev = node;
} else {
System.out.println("pos位置不合法!");
}
}
/**
* 查找关键字
*/
public boolean contains(int key) {
Node cur = this.head;
while (cur != null) {
if (cur.data == key) {
return true;
} else {
cur = cur.next;
}
}
return false;
}
/**
* 删除第一次出现的元素
*/
public void remove(int key){
Node cur =this.head;
if (this.head.data == key){
head = head.next;
head.prev = null;
return;
}
while (cur != null){
if (cur.data == key){
cur.prev.next=cur.next;
if (tail.data == key){
cur.prev.next = cur.next;
tail = cur.prev;
}else{
cur.next.prev = cur.prev;
}
return;
}
cur = cur.next;
}
System.out.println("没有找到删除的元素");
}
/**
* 删除所有相同的元素
*/
public void removeAll(int key){
Node cur = this.head.next;
if (this.head == null){
System.out.println("空链表,没有删除的元素");
return;
}
if (this.head.data == key){
head = cur;
cur.prev = null;
}
while(cur.next!= null){
if (cur.data == key){
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
cur = cur.next;
}else{
cur = cur.next;
}
}
if (tail.data == key){
tail = cur.prev;
tail.next=null;
}
}
/**
* 展示
*
* @param
*/
public void display() {
Node cur = this.head;
if (head == null) {
return;
} else {
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
}
System.out.println();
}
/**
* Szie
*
* @param
*/
public int size() {
Node cur = this.head;
int count = 0;
if (this.head == null) {
return 0;
} else {
while (cur != null) {
count++;
cur = cur.next;
}
}
return count;
}
public static void main(String[] args) {
DoubleLink doubleLink = new DoubleLink();
doubleLink.addLast(3);
doubleLink.addLast(1);
doubleLink.addLast(2);
doubleLink.addLast(2);
doubleLink.addLast(3);
System.out.println("尾插法添加元素");
doubleLink.display();
System.out.println("任意位置插入元素");
doubleLink.addPos(5, 4);
doubleLink.display();
System.out.println("删除第一次出现的元素");
doubleLink.remove(4);
doubleLink.display();
System.out.println("删除key=2的元素");
doubleLink.removeAll(2);
doubleLink.display();
}
}
结果展示如下:
在有单链表基础之后,编写双链表会更加容易,不需要再定义多个节点来互相记忆遍历位置;
需要区别对待的是:双向链表在头插或者尾插的时候就对头节点和尾节点进行标记,后续对链表进行增删查改同时可以直接使用相对应节点操作。