双向链表
上篇博客已将讲解过单向链表,单向链表在实现增删改查时速度还是有所限制,可以通过双向链表更快地实现操作。
1.定义
1.1双向链表定义:
双向链表也是链表的一种,每个数据节点中都有两个指针,一个为pre指向前一个节点(前驱),另一个为next指向下一个节点(后继),因为这个特点,双向链表可以很方便的访问任意节点的前驱节点和后继 节点。
1.2单链表特点:
- 遍历时到达下一个节点很容易,但是无法回到上一个节点
1.3双链表特点:
- 每次插入或删除某个节点时,通常需要处理四个指针的引用,实现起来比单向链表更为复杂
- 占用内存更大
从上中可以看到,双向链表中各节点包含以下 3 部分信息:
指针域:用于指向当前节点的直接前驱节点;
数据域:用于存储数据元素。
指针域:用于指向当前节点的直接后继节点;
2.代码实现
2.1双向链表的节点结构:
class Node
{
public int No;
public String name;
//后继指针
public Node next;
//前驱指针
public Node pre;
public Node(int no, String name) {
No = no;
this.name = name;
}
@Override
public String toString() {
return "Node{" +
"No=" + No +
", name='" + name +
'}';
}
}
2.2插入节点
- 添加至表尾
public void add(Node newNode)
{
Node temp = headNode;
//遍历链表
while (temp.next != null)
{
temp = temp.next;
}
//建立新的前驱后继指针关系
temp.next = newNode;
newNode.pre = temp;
}
- 添加至表的任意位置
两个步骤:1. 新节点先与其后继节点建立双向连接关系 2.新节点与其前驱节点建立双向连接关系
/**
* 这里用按节点编号由小到大顺序添加的方法来演示任意位置插入添加数据
*/
public void addByOrder(Node newNode)
{
if (isEmpty())
{
add(newNode);
return;
}
Node temp = headNode;
boolean isExit = false;
while (true)
{
if (temp.next == null)
{
break;
}
if (temp.No == newNode.No)
{
isExit = true;
break;
}
else if (temp.next.No > newNode.No)
{
break;
}
temp = temp.next;
}
if (isExit)
{
System.out.printf("编号%d已存在,添加失败....",newNode.No);
}
else
{
newNode.next = temp.next;
if (temp.next != null)
{
temp.next.pre = newNode;
}
temp.next = newNode;
newNode.pre = temp;
}
}
2.3删除节点
public void delete(int No)
{
if (isEmpty())
{
System.out.println("当前链表为空");
return;
}
Node temp = headNode.next;
boolean hasFound = false;
while (temp != null)
{
if (temp.No == No)
{
hasFound = true;
break;
}
temp = temp.next;
}
if (hasFound)
{
temp.pre.next = temp.next;
//如果下一个节点为空则不需要执行以下代码
if (temp.next != null)
{
temp.next.pre = temp.pre;
}
}else
{
System.out.println("未找到符合条件的结点,节点删除失败....");
}
}
2.4修改节点
public void update(Node newNode)
{
if (isEmpty())
{
System.out.println("链表为空");
return;
}
Node temp = headNode.next;
boolean hasFound = false;
while (temp != null)
{
if (temp.No == newNode.No)
{
hasFound = true;
break;
}
temp = temp.next;
}
if (hasFound)
{
temp.name = newNode.name;
temp.nickname = newNode.nickname;
}else
{
System.out.println("未找到符合条件的结点,节点修改失败....");
}
}
2.5遍历链表
public void list()
{
if (isEmpty())
{
System.out.println("链表为空");
return;
}
System.out.println("---------------------------------------------------");
Node temp = headNode.next;
while (temp != null)
{
System.out.println(temp+",pre="+temp.pre+",next="+temp.next);
temp = temp.next;
}
System.out.println("---------------------------------------------------");
}
如有错误或不妥欢迎评论指正。