数据结构入门(3)----双向链表

本文介绍了双向链表的概念,每个数据结点包含指向前后结点的指针,便于双向遍历。示例使用Java展示了双向链表节点的结构以及如何按照顺序插入新节点。在插入过程中,特别强调了中间插入时的代码顺序重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在单向链表的基础上,理解双向链表就很简单了。

双向链表,又称为双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表

 1.节点结构示例:

public class DoublyLinkedNode {
    public int num;  //编号
    public String name;  //姓名
    public int age;  //年龄

    public DoublyLinkedNode next;  //指向下一个元素
    public DoublyLinkedNode pre;   //指向上一个元素

    public DoublyLinkedNode(int num, String name, int age) {
        this.num = num;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "DoublyLinkedNode{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.链表结构示例

class DoublyLinkedList{
    //设置一个头节点
    public DoublyLinkedNode head = new DoublyLinkedNode(0,null,0);

    //这里只演示添加

    /**
     * 按照顺序进行插入
     * @param doublyLinkedNode
     */
    public void addByOrder(DoublyLinkedNode doublyLinkedNode){
        // 因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
        DoublyLinkedNode temp = head;
        //判断是否插入成功的标签
        int flag = 0;
        while (true){
            //如果是链表尾部,则跳出循环,直接插入
            if (temp.next == null){
                break;
            }
            //如果已经存在,则插入失败
            if (temp.next.num == doublyLinkedNode.num){
                flag = 1;
                break;
            }
            //按照从小到大插入
            if (temp.next.num > doublyLinkedNode.num){
                flag =2;
                break;
            }
            temp = temp.next;
        }
        //如果是尾插
        if (flag == 0){
            System.out.println(doublyLinkedNode.toString() + "插入成功");
            temp.next = doublyLinkedNode;
            doublyLinkedNode.pre = temp;
        }
        //如果是中间插入
        if (flag == 2){
            System.out.println(doublyLinkedNode.toString() + "插入成功");
            //下面这几行的代码注意执行顺序 TODO 检查
            doublyLinkedNode.next = temp.next;
            temp.next.pre = doublyLinkedNode;
            temp.next = doublyLinkedNode;
            doublyLinkedNode.pre = temp;
//            doublyLinkedNode.next = temp.next;
//            doublyLinkedNode.pre = temp;
//            temp.next.pre = doublyLinkedNode;
//            temp.next = doublyLinkedNode;

        }
        //如果插入失败
        if (flag == 1){
            System.out.println(doublyLinkedNode.toString() + "插入失败");
        }
    }

    public void list(){
        DoublyLinkedNode temp = head;
        while (true){
            if (temp.next != null){
                System.out.println(temp.next + "   他前一个节点为" + temp.next.pre);
            }else {
                break;
            }
            temp = temp.next;
        }
    }
}

3.测试示例

public class DoublyLinkedList_Test {
    public static void main(String[] args) {
        DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
        //添加元素
        doublyLinkedList.addByOrder(new DoublyLinkedNode(3,"张飞",20));
        doublyLinkedList.addByOrder(new DoublyLinkedNode(2,"张飞",20));
        doublyLinkedList.addByOrder(new DoublyLinkedNode(4,"张飞",20));
        doublyLinkedList.addByOrder(new DoublyLinkedNode(1,"张飞",20));
        doublyLinkedList.addByOrder(new DoublyLinkedNode(6,"张飞",20));
        doublyLinkedList.addByOrder(new DoublyLinkedNode(5,"张飞",20));

        //显示链表
        System.out.println("___________________________________________________________");
        doublyLinkedList.list();
    }
}

 4.显示结果

DoublyLinkedNode{num=3, name='张飞', age=20}插入成功
DoublyLinkedNode{num=2, name='张飞', age=20}插入成功
DoublyLinkedNode{num=4, name='张飞', age=20}插入成功
DoublyLinkedNode{num=1, name='张飞', age=20}插入成功
DoublyLinkedNode{num=6, name='张飞', age=20}插入成功
DoublyLinkedNode{num=5, name='张飞', age=20}插入成功
___________________________________________________________
DoublyLinkedNode{num=1, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=0, name='null', age=0}
DoublyLinkedNode{num=2, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=1, name='张飞', age=20}
DoublyLinkedNode{num=3, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=2, name='张飞', age=20}
DoublyLinkedNode{num=4, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=3, name='张飞', age=20}
DoublyLinkedNode{num=5, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=4, name='张飞', age=20}
DoublyLinkedNode{num=6, name='张飞', age=20}   他前一个节点为DoublyLinkedNode{num=5, name='张飞', age=20}

Process finished with exit code 0

 5.注意点

对于下面的插入代码一定要注意顺序,熟悉其传递过程,可以画图,或者debug来深入理解,然后在控制台把前一个结点打印出来验证结果。

            doublyLinkedNode.next = temp.next;
            temp.next.pre = doublyLinkedNode;
            temp.next = doublyLinkedNode;
            doublyLinkedNode.pre = temp;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值