数据结构之链表

链表的基本概念

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

链表的类型

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

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

相关推荐
学编程就要猛2 小时前
数据结构初阶:Java中的Stack和Queue
数据结构
是苏浙2 小时前
零基础入门C语言之C语言实现数据结构之顺序表
c语言·开发语言·数据结构
星释2 小时前
Rust 练习册 :Matching Brackets与栈数据结构
数据结构·算法·rust
逐步前行5 小时前
C数据结构--排序算法
c语言·数据结构·排序算法
_dindong6 小时前
笔试强训:Week-4
数据结构·c++·笔记·学习·算法·哈希算法·散列表
陌路207 小时前
S12 简单排序算法--冒泡 选择 直接插入 希尔排序
数据结构·算法·排序算法
papership8 小时前
【入门级-算法-5、数值处理算法:高精度的乘法】
数据结构·算法
earthzhang20218 小时前
【1039】判断数正负
开发语言·数据结构·c++·算法·青少年编程
谈笑也风生8 小时前
只出现一次的数字 II(一)
数据结构·算法·leetcode
im_AMBER9 小时前
Leetcode 47
数据结构·c++·笔记·学习·算法·leetcode