数据结构之链表

链表的基本概念

链表是一种线性数据结构,由一系列节点组成,每个节点包含数据域和指针域。数据域存储数据,指针域存储下一个节点的地址。链表可以动态分配内存,不需要预先知道数据量的大小。

链表的类型

  1. 单链表:每个节点只有一个指针域,指向下一个节点。
  2. 双链表:每个节点有两个指针域,分别指向前一个节点和后一个节点。
  3. 循环链表:尾节点的指针域指向头节点,形成一个环。

链表的操作

插入节点

在链表中插入节点需要调整指针的指向。例如,在单链表中插入一个新节点:

  • 新节点的指针指向原位置的下一个节点。
  • 原位置的指针指向新节点。

删除节点

删除节点时,需要将前一个节点的指针指向被删除节点的下一个节点。例如,在单链表中删除一个节点:

  • 找到待删除节点的前驱节点。
  • 将前驱节点的指针指向待删除节点的后继节点。

遍历链表

从头节点开始,依次访问每个节点,直到指针域为 null。

链表的优缺点

优点

  • 动态内存分配,不需要预先知道数据量。
  • 插入和删除操作高效,时间复杂度为 O(1)(已知位置时)。

缺点

  • 访问元素需要从头遍历,时间复杂度为 O(n)。
  • 需要额外的空间存储指针。

链表的代码实现(JAVA)

java 复制代码
/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: zhany
 * Date: 2025-10-13
 * Time: 11:55
 */
public class MyLink implements IList{
    static class ListNode {
        int val;
        ListNode prev;
        ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head;
    public ListNode last;
    @Override
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        if (head == null) {
            head = last  = node;
        } else {
            node.next = head;
            head.prev = node;
            head = node;
        }
        }

    @Override
    public void addLast(int data) {
    ListNode node = new ListNode(data);
        if (last == null) {
            head = last = node;
        } else {
            last.next = node;
            node.prev = last;
            last = node;
        }
    }

    @Override
    public boolean addIndex(int index, int data) {
        int len = size();
        if(len < 0 || len > size()){
            return false;
        }
        if (len == 0) {
            addFirst(data);
        }
        if (len == size()){
            addLast(data);
        }
        ListNode cur = findindex(index);
        ListNode node  =new ListNode(data);
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;

        return true;
    }
    private ListNode findindex(int index) {
        ListNode cur = head;
        while(index == 0){
            cur  =cur.next;
            index--;
        }
        return cur;
    }

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

    @Override
    public void remove(int key) {
        ListNode cur  = head;
    while(cur != null){
        if (cur.val == key){
            if (cur == head) {
                head = head.next;
                if (head != null) {
                    head.prev = null;
                }
            } else {
                cur.prev.next = cur.next;
                if (cur.next == null) {
                    last = last.prev;
                } else {
                    cur.next.prev = cur.prev;
                }
            }
            return;
        }
        cur = cur.next;
    }
    }

    @Override
    public void removeAllKey(int key) {
        ListNode cur = head;
        while(cur != null){
            if (cur == head) {
                head = head.next;
                if (head.prev != null) {
                    head.prev = null;
                }

            } else{
                cur.prev.next = cur.next;
                if (cur.next == null) {
                    last = last.prev;
                } else {
                    cur.next.prev = cur.prev;
                }
            }
            cur =cur.next;
        }

    }

    @Override
    public int size() {
        ListNode cur = head;
        int len = 0;
        while (cur != null && cur.next !=null){
            cur = cur.next;
            len++;
        }
        return len;
    }

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

    @Override
    public void clear() {
        ListNode cur = head;
        while(cur != null){
            ListNode curN =cur.next;
            cur.prev =null;
            cur.next = null;
            cur = curN;
        }
        last = head = null;
    }
}

链表的应用场景

  1. 动态内存管理:适用于需要频繁插入和删除的场景。
  2. 实现其他数据结构:如栈、队列、哈希表等。
  3. 文件系统:文件目录结构可以用链表表示。

链表是一种基础但强大的数据结构,理解其原理和实现方式对编程和算法学习至关重要。

相关推荐
m0_547486663 天前
《数据结构教程》全套 PPT课件2026
数据结构
tryxr3 天前
矩阵的几种基础变换
java·数据结构·算法·矩阵
mmmmath_33 天前
LeetCode.028.找出字符串中第一个匹配项的
数据结构·算法·leetcode
All for pursuit.3 天前
【栈-4】739.每日温度
数据结构·c++·算法·leetcode
All for pursuit.3 天前
【栈-5】84.柱状图中最大的矩形
数据结构·c++·算法·leetcode
渡我白衣3 天前
HttpRequest与HttpResponse的实现
服务器·数据结构·c++·人工智能·tcp/ip·机器学习·caffe
晴天的雨.9923 天前
【C++算法】和为s的两个数
开发语言·数据结构·c++·算法
无敌贵点大王4 天前
RTThread学习记录11——RT-Thread 设备模型吃透:UART/ADC/PWM/PIN 到底有什么区别?
c语言·stm32·学习·链表
淡海水4 天前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Logic1014 天前
C语言/数据结构位运算题解:异或XOR找出时尚聚会中的“独特颜色“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质