数据结构:双向链表

双向链表

上篇博客已将讲解过单向链表,单向链表在实现增删改查时速度还是有所限制,可以通过双向链表更快地实现操作。

1.定义

1.1双向链表定义:

​ 双向链表也是链表的一种,每个数据节点中都有两个指针,一个为pre指向前一个节点(前驱),另一个为next指向下一个节点(后继),因为这个特点,双向链表可以很方便的访问任意节点的前驱节点和后继 节点。

1.2单链表特点:
  1. 遍历时到达下一个节点很容易,但是无法回到上一个节点
1.3双链表特点:
  1. 每次插入或删除某个节点时,通常需要处理四个指针的引用,实现起来比单向链表更为复杂
  2. 占用内存更大

在这里插入图片描述

从上中可以看到,双向链表中各节点包含以下 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("---------------------------------------------------");
}

如有错误或不妥欢迎评论指正。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又蠢又笨的懒羊羊程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值