在上一篇文章 数据结构:链表《概念》中已经介绍了什么是链表以及链表的特性是什么,废话不多说直接上干货如果实现一个双链表。
双向链表与单向链表相比较,双向链表可以从头到尾或从尾到头两个方向来遍历数据。双向链表中的节点分三个部分,分别是指向上一个节点的地址(prev)和数据(data)以及指向下一个节点的地址(next),尾节点(tail)节点的 next 指向 null,头节点(head)的 prev 指向 null,增加和删除节点和单向链表同理,只是增加了修改 prev 地址的操作.
无头双向非循环链表接实现
private static class LinkedNode{
private int key;
private String value;
//上一个节点
private LinkedNode prevNode;
//下一个节点
private LinkedNode nextNode;
public LinkedNode(int key, String value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public LinkedNode getNextNode() {
return nextNode;
}
public void setNextNode(LinkedNode nextNode) {
this.nextNode = nextNode;
}
@Override
public String toString() {
return "LinkedNode{" +
"key=" + key +
", value='" + value + ''' +
'}';
}
}
链表头部插法插入
头插法就是从头部插入节点,使新创建的节点成为新的头结点,这里需要额外考虑一个点,就是头结点是否存在,不光要设置后驱还要注意前驱,这比单链表多一个前驱节点
/**
* 从链表头部添加
* @param node
* @return
*/
public DoubleLinkedNodeList addLinkedNodeToHead(LinkedNode node) {
if (Objects.isNull(this.headLinkedNode)) {
this.tailLinkedNode = node;
} else {
node.nextNode = this.headLinkedNode;
this.headLinkedNode.prevNode = node;
}
this.headLinkedNode = node;
length++;
return this;
}
根据头部添加方法执行逻辑图
最终形成双链表
链表尾部插法插入
尾插法和头插法类似,必须先判断链表是否为空,双链表区别于单链表,不用每次遍历来找尾节点,双链表本身就有一个尾节点last,我们只需要找到这个last,然后将新节点插入即可
/**
* 从链表尾添加
* @param node
*/
public DoubleLinkedNodeList addLinkedNodeToTail(LinkedNode node){
//添加一个新节点,储存要插入的数据的时候判断头节点是否存在
if (Objects.isNull(this.headLinkedNode)) {
//判断头节点是否为空,头节点空说明链表为空
//头节点为null属于第一次插入,直接将头节点尾节点都指向插入节点
this.headLinkedNode=node;
this.tailLinkedNode=node;
}else{
//将新节点变成原尾节点的后驱,实现尾插
this.tailLinkedNode.nextNode=node;
//再将原尾节点变成新插入节点的前驱
node.prevNode=tailLinkedNode;
//最后将新插入节点设置成尾节点
this.tailLinkedNode=node;
}
length++;
return this;
}
尾部执行逻辑图与头部指向逻辑图查类似就不再画了,下面直接干货上代码。
完整代码
import java.util.Objects;
/**
* @ClassName DoubleLinkedNodeDemo
* @Description 双链表
*/
public class DoubleLinkedNodeDemo {
public static void main(String[] args) {
LinkedNode node6 = new LinkedNode(6, "A6");
LinkedNode node1 = new LinkedNode(1, "A1");
LinkedNode node2 = new LinkedNode(2, "A2");
LinkedNode node5 = new LinkedNode(5, "A5");
LinkedNode node3 = new LinkedNode(3, "A3");
LinkedNode node4 = new LinkedNode(4, "A4");
LinkedNode node7 = new LinkedNode(7, "A7");
/* System.out.println(">>>>>>>>>>>>>>>从头部添加节点");
DoubleLinkedNodeList doubleLinkedNodeList = new DoubleLinkedNodeList ();
doubleLinkedNodeList
.addLinkedNodeToHead(node6)
.addLinkedNodeToHead(node1)
.addLinkedNodeToHead(node2)
.addLinkedNodeToHead(node5)
.addLinkedNodeToHead(node3)
.addLinkedNodeToHead(node4)
.addLinkedNodeToHead(node7);
doubleLinkedNodeList.print();*/
System.out.println(">>>>>>>>>>>>>>>从尾部添加节点");
DoubleLinkedNodeList doubleLinkedNodeList = new DoubleLinkedNodeList ();
doubleLinkedNodeList
.addLinkedNodeToTail(node6)
.addLinkedNodeToTail(node1)
.addLinkedNodeToTail(node2)
.addLinkedNodeToTail(node5)
.addLinkedNodeToTail(node3)
.addLinkedNodeToTail(node4)
.addLinkedNodeToTail(node7);
doubleLinkedNodeList.print();
System.out.println(">>>>>>>>>>>>>>>获取节点");
LinkedNode linkedNode= doubleLinkedNodeList.getLinkedNode(4);
System.out.println(linkedNode.toString());
System.out.println(">>>>>>>>>>>>>>>删除节点");
doubleLinkedNodeList.removeLinkedNode(node5).print();
System.out.println(">>>>>>>>>>>>>>>修改节点");
doubleLinkedNodeList.updateLinkedNode(new LinkedNode(7, "A777777")).print();
System.out.println(">>>>>>>>>>>>>>>按照顺序添加");
DoubleLinkedNodeList doubleLinkedNodeListSort = new DoubleLinkedNodeList ();
doubleLinkedNodeListSort
.addLinkedNodeSort(node6)
.addLinkedNodeSort(node1)
.addLinkedNodeSort(node2)
.addLinkedNodeSort(node5)
.addLinkedNodeSort(node3)
.addLinkedNodeSort(node4)
.addLinkedNodeSort(node7);
doubleLinkedNodeListSort.print();
}
private static class DoubleLinkedNodeList{
//定义链表头部节点
private LinkedNode headLinkedNode ; //双链表的头部第一个节点
private LinkedNode tailLinkedNode ; //双链表的尾部最后一个节点
public DoubleLinkedNodeList() {
headLinkedNode = null;
tailLinkedNode = headLinkedNode;
}
/**
* 从链表头部添加
* @param node
* @return
*/
public DoubleLinkedNodeList addLinkedNodeToHead(LinkedNode node) {
//添加一个新节点,储存要插入的数据的时候判断头节点是否存在
if (Objects.isNull(this.headLinkedNode)) {
//判断头节点是否为空,头节点空说明链表为空
//头节点为null属于第一次插入,直接将头节点尾节点都指向插入节点
this.tailLinkedNode = node;
this.headLinkedNode = node;
} else {
node.nextNode = this.headLinkedNode;
this.headLinkedNode.prevNode = node;
this.headLinkedNode = node;
}
return this;
}
/**
* 按照顺序添加
*
* @param node
*/
public DoubleLinkedNodeList addLinkedNodeSort(LinkedNode node) {
if (Objects.isNull(this.headLinkedNode)) {
this.headLinkedNode = node;
this.tailLinkedNode = node;
return this;
}
// node比头节点小,将node设为头节点
if (this.headLinkedNode.key > node.key) {
this.headLinkedNode.prevNode = node;
node.nextNode = this.headLinkedNode;
this.headLinkedNode = node;
return this;
}
// node比尾节点大,将node设为尾节点
if (this.tailLinkedNode.key < node.key) {
this.tailLinkedNode.nextNode = node;
node.prevNode = this.tailLinkedNode;
this.tailLinkedNode = node;
return this;
}
LinkedNode temp = this.headLinkedNode.nextNode;
while (true) {
if (temp.key > node.key) {
node.nextNode = temp;
node.prevNode = temp.prevNode;
temp.prevNode.nextNode = node;
temp.prevNode = node;
break;
}
temp = temp.nextNode;
}
return this;
}
/**
* 从链表尾添加
* @param node
*/
public DoubleLinkedNodeList addLinkedNodeToTail(LinkedNode node){
//添加一个新节点,储存要插入的数据的时候判断头节点是否存在
if (Objects.isNull(this.headLinkedNode)) {
//判断头节点是否为空,头节点空说明链表为空
//头节点为null属于第一次插入,直接将头节点尾节点都指向插入节点
this.headLinkedNode=node;
this.tailLinkedNode=node;
}else{
//将新节点变成原尾节点的后驱,实现尾插
this.tailLinkedNode.nextNode=node;
//再将原尾节点变成新插入节点的前驱
node.prevNode=tailLinkedNode;
//最后将新插入节点设置成尾节点
this.tailLinkedNode=node;
}
return this;
}
/**
* 获取节点
* @param key
* @return
*/
public LinkedNode getLinkedNode(int key) {
if (Objects.isNull(this.headLinkedNode)) {
return null;
}
LinkedNode tempLinkedNode = this.headLinkedNode;
while (Objects.nonNull(tempLinkedNode.key)) {
if (tempLinkedNode.key == key) {
return tempLinkedNode;
}
tempLinkedNode = tempLinkedNode.nextNode;
}
return null;
}
/**
* 删除节点
* @param node
* @return
*/
public DoubleLinkedNodeList removeLinkedNode(LinkedNode node) {
if (Objects.isNull(this.headLinkedNode)) {
return this;
}
// 要移除的是头节点
if (this.headLinkedNode == node) {
this.headLinkedNode.nextNode.prevNode = null;
this.headLinkedNode = this.headLinkedNode.nextNode;
return this;
}
// 要移除的是尾节点
if ( this.tailLinkedNode == node) {
this.tailLinkedNode.prevNode.nextNode = null;
this.tailLinkedNode = this.tailLinkedNode.prevNode;
return this;
}
LinkedNode temp = this.headLinkedNode.nextNode;
while ( Objects.nonNull(temp)) {
if (temp.key == node.key) {
temp.prevNode.nextNode = temp.nextNode;
temp.nextNode.prevNode = temp.prevNode;
break;
}
temp = temp.nextNode;
}
return this;
}
/**
* 修改某个节点
*
* @param node
*/
public DoubleLinkedNodeList updateLinkedNode(LinkedNode node) {
if (Objects.isNull(this.headLinkedNode)) {
return this;
}
LinkedNode temp = this.headLinkedNode;
while ( Objects.nonNull(temp)) {
if (temp.key == node.key) {
temp.value = node.value;
break;
}
temp = temp.nextNode;
}
return this;
}
/**
* 打印链表节点的数据
*/
public void print() {
if ( Objects.isNull(headLinkedNode)) {
return;
}
LinkedNode temp = headLinkedNode;
while (Objects.nonNull(temp)) {
System.out.println(temp);
temp = temp.nextNode;
}
}
}
private static class LinkedNode{
private int key;
private String value;
//上一个节点
private LinkedNode prevNode;
//下一个节点
private LinkedNode nextNode;
public LinkedNode(int key, String value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public LinkedNode getNextNode() {
return nextNode;
}
public void setNextNode(LinkedNode nextNode) {
this.nextNode = nextNode;
}
@Override
public String toString() {
return "LinkedNode{" +
"key=" + key +
", value='" + value + ''' +
'}';
}
}
}