双向链表
简介
双向链表是基于单链表的基础上,每个节点中添加了一个指向上一个节点的指针。相对单链表而言,双向链表中的增删除改更为方便。例如,双链表可以便捷地进行自我删除的(单链表则需要借助辅助节点),届时只需要需要删除节点的相邻节点进行链接,便可实现自我删除。
功能实现
定义双链表节点
在单链表的基础上,添加一个存储上一个节点的指针。
class Node {
int no;
String name;
Node next;
Node pre;
/**
* 构造函数
*/
public Node(int no, String data) {
this.no = no;
this.name = data;
}
}
遍历
- 双链表的遍历也是和单链表一样的。只需要从头结点开始,逐个遍历便可。判断题条件是当前节点的下一个节点不为空(temp.next != null)。
- 完整代码:
public void printAll() {
if (headNode.next == null) {
System.out.println("链表为空~!");
return;
}
Node temp = headNode;
while (null != temp.next) {
temp = temp.next;
System.out.println("编号: " + temp.no + " \t姓名:" + temp.name);
}
}
顺序添加节点
- 头节点为空,则直接添加
- 反之,获取最后一个节点,再添加
- 需要注意的是,别忘了处理新增节点的上一个指针的地址指向。
- 完整代码:
/**
* 添加节点到双向链表的末尾
*
* @param node {@link Node} 新增节点
*/
public void add(Node node) {
Node temp = this.headNode;
while (null != temp.next) {
temp = temp.next;
}
temp.next = node;
node.pre = temp;
}
根据内容(Node.name)修改节点
- 遍历链表,比对索引,相同修改,没有就算了
- 比较简单,直接贴代码了:
/**
* 根据索引修改节点内容
*
* @param index 节点索引
* @param name 修改内容
*/
public void modify(int index, String name) {
if (null == headNode.next) {
System.out.println("该链表为空~!");
return;
}
Node temp = this.headNode;
while (null != temp.next) {
temp = temp.next;
if (index == temp.no) {
temp.name = name;
return;
}
}
System.out.println("没有找到该索引!");
}
通过索引修改整个节点
- 遍历链表,比对链表,符合则替换整个链表
- 注意链表的上下指针的指向。
- 代码实现:
/**
* 通过索引修改整个节点
*
* @param index 节点索引
* @param node {@link Node} 新的节点
*/
public void modify(int index, Node node) {
if (this.headNode.next == null) {
System.out.println("该链表为空~!");
return;
}
Node temp = this.headNode;
while (null != temp.next) {
temp = temp.next;
if (temp.no == index) {
node.next = temp.next;
node.pre = temp.pre;
temp.pre.next = node;
temp.next.pre = node;
return;
}
}
System.out.println("没有找到该索引!");
}
通过索引删除节点
- 代码实现:
/**
* 删除索引某个节点
*
* @param index 节点索引
*/
public void delete(int index) {
if (this.headNode.next == null) {
System.out.println("该链表为空~!");
return;
}
Node temp = this.headNode;
while (null != temp.next) {
temp = temp.next;
if (index == temp.no) {
temp.pre.next = temp.next;
// 若为链表的最后一个节点,则不用处理 其一个节点的信息
if (temp.next != null) {
temp.next.pre = temp.pre;
}
return;
}
}
System.out.println("没有找到该节点~!");
}
按顺序添加节点
- 遍历节点,比较索引,较大者后置
- 代码实现:
/**
* 按顺序添加
*
* @param node {@link Node} 新增节点
*/
public void addByOrder(Node node) {
if (this.headNode.next == null) {
this.headNode.next = node;
node.pre = this.headNode.next;
return;
}
Node temp = this.headNode;
while (temp.next != null) {
temp = temp.next;
if (temp.no >= node.no) {
temp.pre.next = node;
node.pre = temp.pre;
node.next = temp;
temp.pre = temp;
return;
}
}
temp.next = node;
node.pre = temp;
}
完整代码
因为完整代码比较长,这里就贴一下伪代码就好了,方便查看
- 完整代码(伪代码):
class DoubleLinkedList {
/**
* 双链表的头节点(不作为存储数据的节点)
*/
private final Node headNode = new Node(0, null);
/**
* 按顺序添加
*/
public void addByOrder(Node node) {
···
}
/**
* 删除索引某个节点
*
* @param index 节点索引
*/
public void delete(int index) {
····
}
/**
* 通过索引修改整个节点
*
* @param index 节点索引
* @param node {@link Node} 新的节点
*/
public void modify(int index, Node node) {
···
}
/**
* 根据索引修改节点内容
*
* @param index 节点索引
* @param name 修改内容
*/
public void modify(int index, String name) {
···
}
/**
* 添加节点到双向链表的末尾
*
* @param node {@link Node} 新增节点
*/
public void add(Node node) {
···
}
/**
* 遍历双向链表
*/
public void printAll() {
···
}
}
/**
* 双向链表的节点
*/
class Node {
int no;
String name;
Node next;
Node pre;
public Node(int no, String data) {
this.no = no;
this.name = data;
}
}
小结
双链表比单链表多了一个指向上一个节点的指针,真的是太好了,在单链表中需要通过多个临时变量来完成的操作,在双链表中都可以完美快速的解决。总体来说还是很完美的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。