数据结构之双向链表详解

本文详细介绍了如何模拟实现无头双向链表,包括定义IList接口、重写关键方法如添加、删除和查找,以及LinkedList的使用场景和常见面试问题。

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

😽博主优快云主页:小源_😽

🖋️个人专栏:《数据结构》🖋️

😀努力追逐大佬们的步伐~


 目录

1. 前言

2. LinkedList(无头双向链表)的模拟实现

2.1 定义IList接口

2.2 重写IList中的方法

2.3 display(打印方法)

2.4 size方法

2.5 contains方法

2.6 addFirst头插法

2.7 addLast尾插法

2.8 addIndex任意插法

2.9 remove方法

2.10 removeAllKey方法

2.11 clear方法

3. LinkedList的使用

3.1 什么是LinkedLList

3.2 LinkedList的使用

3.3 LinkedList的遍历

4. 经常遇到的面试问题


1. 前言

上一篇文章中我们重点讲解了无头单向非循环链表的模拟实现,现在我们来讲解LinkedList(无头双向链表实现 )的模拟实现。

本章重点:

本文着重讲解了LinkedList(无头双向单链表)的实现和LinkedList的使用。 


2. LinkedList(无头双向链表)的模拟实现

  

 从上图可以看出,无头双向链表和无头单向非循环链表结构类似,只是在每个节点中加入了前一个节点的地址(用prev存储),使得每个节点可以访问前一个节点。其中第一个节点的前驱prev为空。

2.1 定义IList接口

无头双向链表的模拟实现要定义的接口和上一篇文章中无头单向非循环链表的模拟实现一样,即:

public interface IList {
    //头插法
    void addFirst(int data); 
    //尾插法
    void addLast(int data);
    //任意位置插入,第一个数据节点为0号下标
    void addIndex(int index,int data);
    //查找是否包含关键字key是否在单链表当中
    boolean contains(int key);
    //删除第一次出现关键字为key的节点
    void remove(int key);
    //删除所有值为key的节点
    void removeAllKey(int key);
    //得到单链表的长度
    int size();
    //清空
    void clear();
    //打印
    void display();
}

2.2 重写IList中的方法

定义一个MyLinkedList类来实现IList接口,并且重写IList中的方法

(选中IList,快捷键为Ctrl+O):

首先需要定义一个内部类作为节点的类,用static修饰,代表只能在当前类中使用。

接着定义一个头节点head,尾节点last

 

public class MyLinkedList implements IList{
    static class ListNode {
        public int val;
        public ListNode next;
        public ListNode prev;

        public ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode head;
    public ListNode last;

    @Override
    public void addFirst(int data) {

    }

    @Override
    public void addLast(int data) {

    }

    @Override
    public void addIndex(int index, int data) {

    }

    @Override
    public boolean contains(int key) {
        return false;
    }

    @Override
    public void remove(int key) {

    }

    @Override
    public void removeAllKey(int key) {

    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public void clear() {

    }

    @Override
    public void display() {
        ListNode cur = head;
        while (cur != null) {
            System.out.println(cur.next + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}
​

2.3 display(打印方法)

遍历双向链表的方法和遍历单链表相同:我们只需关心next域,而不需要关心prev。

@Override
    public void display() {
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}

2.4 size方法

求链表个数/长度

@Override
    public int size() {
        ListNode cur = head;
        //定义一个计数器
        int count = 0;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

2.5 contains方法

指的是查找是否包含关键字key是否在单链表当中。这里跟size方法相似,只需遍历链表时判断是否cur.val == key

@Override
    public boolean contains(int key) {
        ListNode cur = head;
        while (cur != null) {
            //判断
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

2.6 addFirst头插法

指的是将插入的节点存放在链表的第一个位置。

1.实例化一个节点

2.改变插入节点的next和prev

3.改变head

@Override
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        //如果head为空,则head和last都指向node
        if (head == null) {
            head = node;
            last = node;
        } else {
            node.next = 
评论 58
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值