数据结构之链表

链表的基本概念

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

链表的类型

  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. 文件系统:文件目录结构可以用链表表示。

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

相关推荐
Han.miracle5 小时前
数据结构——二叉树的从前序与中序遍历序列构造二叉树
java·数据结构·学习·算法·leetcode
独自破碎E7 小时前
判断链表是否为回文
数据结构·链表
liu****11 小时前
8.list的模拟实现
linux·数据结构·c++·算法·list
武帝为此14 小时前
【B树与B+树详解】
数据结构·b树
南莺莺14 小时前
邻接矩阵的基本操作
数据结构·算法··邻接矩阵
观望过往14 小时前
【Java数据结构】队列详解与经典 OJ 题目实战
java·数据结构
aramae15 小时前
详细分析平衡树--红黑树(万字长文/图文详解)
开发语言·数据结构·c++·笔记·算法
CHEN5_0215 小时前
【leetcode100】和为k的子数组(两种解法)
java·数据结构·算法
guguhaohao17 小时前
list,咕咕咕!
数据结构·c++·list