双向链表
- 单链表的缺点
(1)查找的方向只能是一个方向
(2)单链表不能自我删除,需要依靠辅助节点 - 双向链表的特点
(1)查找的方向有两个。
(2)可以进行自我删除,删除操作不需要辅助节点
节点
双向链表中每个节点需要有两个指向其它节点的指针,它们分别指向链表中的下一个节点,和链表中的上一个节点。
代码:
/**
* 节点类:四个属性id, name, next, pre
* @author dxt
*
*/
class Node2{
public int id; //节点的唯一标识符
public String name; //模拟节点中的数据
public Node2 next; //指向下一个节点的指针,默认初始为空
public Node2 pre; //指向上一个节点的指针默认初始为空
//构造器
public Node2(int id, String name) {
this.id = id;
this.name = name;
}
//重写toString()方法
@Override
public String toString() {
return "Node2 [id=" + id + ", name=" + name + "]";
}
}
实现的方法
void add(Node2 node)
:向双向链表尾添加节点。void printList()
:从头遍历,输出链表。void update(Node2 node)
:将链表中与 node节点相同id的节点的 数据(name)改为node节点的数据。void delete(int nodeId)
:删除链表中节点id为nodeId的节点。
实现代码
代码
/**
* 实现双链表类
*/
public class DoubleLinkedListDemo {
public static void main(String[] args) {
//测试DoubleLinkedList类
System.out.println("测试双向链表的实现");
//1. 创建节点
Node2 n1 = new Node2(1, "张三");
Node2 n2 = new Node2(2, "李四");
Node2 n3 = new Node2(3, "王五");
Node2 n4 = new Node2(4, "王老五");
//2. 创建一个双向链表
DoubleLinkedList dll = new DoubleLinkedList();
dll.add(n1);
dll.add(n2);
dll.add(n3);
dll.add(n4);
dll.printList();
dll.delete(1);
dll.delete(0);
dll.printList();
Node2 n5 = new Node2(4, "灰太狼");
dll.update(n5);
dll.printList();
}
}
/**
* 节点类:四个属性id, name, next, pre
* @author dxt
*
*/
class Node2{
public int id; //节点的唯一标识符
public String name; //模拟节点中的数据
public Node2 next; //指向下一个节点的指针,默认初始为空
public Node2 pre; //指向上一个节点的指针默认初始为空
//构造器
public Node2(int id, String name) {
this.id = id;
this.name = name;
}
//重写toString()方法
@Override
public String toString() {
return "Node2 [id=" + id + ", name=" + name + "]";
}
}
/**
* 实现一个具有头节点的双向链表
* @author dxt
*
*/
class DoubleLinkedList{
//头节点
private Node2 headNode = new Node2(0, "");
//获取头节点
public Node2 getHeadNode() {
return headNode;
}
/**
* 向链表尾添加节点
* @param node
*/
public void add(Node2 node) {
//定义一个辅助节点
Node2 temp = headNode;
while(true) { //定位到链表尾
if(temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = node; //添加到链表尾
node.pre = temp;
}
/**
* 从头遍历 输出链表
*/
public void printList() {
//1.判断链表是否为空
if(headNode.next == null) {
System.out.println("链表为空。。。");
return;
}
//2. 遍历输出
Node2 temp = headNode.next;
while(temp != null) {
System.out.println(temp);
temp = temp.next; //后移
}
}
/**
* 将链表中与 node节点相同id的节点的 数据(name)改为node节点的数据
* @param node
*/
public void update(Node2 node) {
//1. 判断链表是否为空
if(headNode.next == null) {
System.out.println("链表为空,没有数据可以更改。");
return;
}
//2. 查找到对应节点。需要注意:链表不为空时,也可能不包括要修改的节点
Node2 temp = headNode.next;
boolean find = false;
while(true) {
if(temp == null) {
break;
}
if(temp.id == node.id) {
find = true;
break;
}
temp = temp.next;
}
//3. 更改节点数据
if(find) {
temp.name = node.name;
}else {
System.out.println("链表中没有对应节点,修改失败。");
}
}
/**
* 删除链表中节点id为nodeId的节点
* @param id
*/
public void delete(int nodeId) {
//1. 判断链表是否为空
if(headNode.next == null) {
System.out.println("链表为空,删除失败。");
return;
}
//2. 查找对应节点。需要注意链表中没有对应id的节点
Node2 temp = headNode.next;
boolean find = false; //表示链表中没有对应id的节点
while(true) {
if(temp == null) {
break;
}
if(temp.id == nodeId) {
find = true; //找到对应节点
break;
}
temp = temp.next;
}
//3. 删除操作
if(find) {
temp.pre.next = temp.next;
if(temp.next != null) { //当删除最后一个节点时,temp.next=null
temp.next.pre = temp.pre;
}
}else {
System.out.println("链表中没有对应id的节点,删除失败。");
}
}
}
结果