【数据结构】单向链表的原理及实现

简介: 【数据结构】单向链表的原理及实现

1.什么是单链表

链表里的数据是以节点的方式表示的,每一个结点的组成是由:元素+指针来组成的,元素就是存储数据里的存储单元,指针就是用来连接每一个结点的地址数据。这个以结点的序列来表示线性表被称作为单链表。

单链表是一种链式储存结构。在物理储存单元不连续,非顺序。

  • 结点里的数据域是用来存储数据元素的
  • 指针是用于指向下一个具有相同结构的结点
  • 因为只有一个指针结点,故而被称为单链表


b0d1eb6241c849b9be7e8852611fc35e.jpg

2.单链表的实现

末尾增加元素 void add(T data)
指定下标增加元素 void add(int index,T data)
删除指定下标元素 void delete(int index)
获取指定下标的元素 T get(int index)
修改指定下标的元素 void update(int index,T data)
遍历输出所有元素 void show()
获取链表的长度 int length()

(1)定义数据节点实体

a646a0461e9e4bcf9815f0265b5fcac4.jpg

(2)向链表末尾增加元素

0b35b5677bf24aafbec6489e246868b8.jpg

(3)指定下标向链表增加元素

0b35b5677bf24aafbec6489e246868b8.jpg

(4)删除指定下标元素的数据

51a9538df2a94734a763546468b72f9d.jpg

(5)修改指定下标的元素

a4684099578a489286b54f7ecf10ad5c.jpg

(6)获取指定下表的元素

5840669ddd5b4f27a1a279c468eb4d33.jpg

(7)循环遍历输出

b4918c6cb8744654a74eefc8dd744bc7.jpg

(8)获取当前有效的元素个数

c83388267fbb4c4e8567db334f1dbb1a.jpg

3.单链表测试

(1)整体代码实现

public class SingleLinkedList<T> {
    /**
     * 定义头节点
     */
    public Node<T> head = new Node<>(null);
    /**
     * 链表有效元素个数
     */
    private int length=0;
    /**
     * 向单链表中添加一个元素
     * @param data
     */
    public void add(T data){
        //定义当前数据
        Node<T> nodeData = new Node<>(data);
        //定义辅助指针
        Node<T> cur = head;
        //while 循环不断遍历找到最后一个节点
        while (cur.next != null) {
            //只要有下一个节点,辅助指针就向下移动一位
            cur = cur.next;
        }
        //while循环之后,cur已经是最后一个节点,将data赋值到cur的下一个节点上
        cur.next = nodeData;
        //整体链表长度++
        length++;
    }
    /**
     * 向单链表中添加一个元素
     * @param data
     */
    public void add(int index,T data){
        //判断index是否合法
        if(index <0 || index >length){
            System.out.println("index不合法");
            return;
        }
        //定义当前数据
        Node<T> nodeData = new Node<>(data);
        //定义辅助指针
        Node<T> cur = head;
        //找到当前index的元素
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        //将当前节点的next设置成cur的next
        nodeData.next = cur.next;
        //将cur.next设置成nodeData(当前节点)
        cur.next = nodeData;
        //整体链表长度++
        length++;
    }
    /**
     * 遍历输出链表中全部节点
     */
    public void show(){
        //定义辅助指针
        Node<T> cur = head;
        //判断链表中是否存在元素
        if (cur.next == null){
            System.out.println("当前单向链表中元素为空");
            return;
        }
        while (cur.next != null){
            System.out.print(cur.next.data+" ");
            cur = cur.next;
        }
        System.out.print("\n");
    }
    /**
     * 修改指定下标的数据
     * @param index
     * @param data
     */
    public void update(int index,T data){
        Node<T> cur = head;
        if(index > length){
            System.out.println("当前index查过边界");
            return;
        }
        //遍历寻找指定index的节点
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        //找到之后将新的data赋值上去
        cur.data = data;
    }
    /**
     * 删除指定下标元素
     * @param data
     */
    public void delete(int index){
        Node<T> cur = head;
        if(index > length){
            System.out.println("当前index超过边界");
            return;
        }
        //遍历寻找指定index的节点
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        //找到之后将新的data赋值上去,将后一个data赋值到当前节点上
        cur.data = cur.next.data;
        //将当前节点的next变成当前节点的next.next相当于将当前元素的next节点删掉
        cur.next = cur.next.next;
        //单链表整体有效元素减一
        length--;
    }
    /**
     * 获取指定下标元素的数据
     * @param index
     * @return
     */
    public T get(int index){
        //校验参数是否合法
        if(index<0 || index>length){
            System.out.println("当前index超过边界");
        }
        //定义辅助节点
        Node<T> cur = head;
        //找到对应下标的node
        for (int i = 0; i <=index; i++) {
            cur = cur.next;
        }
        //返回node.data
        return cur.data;
    }
    /**
     * 获取单链表的长度
     * @return
     */
    public int length(){
        return this.length;
    }
    /**
     * 内部节点类
     * @param <T>
     */
    class Node<T>{
        /**
         * 定义数据
         */
        public T data;
        /**
         * 定义下一个节点的
         */
        public Node<T> next;
        public Node(T data) {
            this.data = data;
        }
    }
}

(2)测试代码

public class Main {
    public static void main(String[] args) {
        SingleLinkedList<Integer> singleLink = new SingleLinkedList<>();
        //增加元素
        singleLink.add(1);
        singleLink.add(2);
        singleLink.add(3);
        System.out.print("新增之后:");
        singleLink.show();
        //删除元素
        singleLink.delete(0);
        System.out.print("删除index为0之后:");
        singleLink.show();
        //修改元素
        singleLink.update(0,9);
        System.out.print("修改index为0之后:");
        singleLink.show();
        //获取单链表的长度
        int length = singleLink.length();
        System.out.println("单链表的长度:"+length);
        //获取指定下标的数据
        System.out.println("获取指定下标的数据:"+singleLink.get(1));
        //指定下标插入数据
        singleLink.add(1,6);
        System.out.print("在index为1位置插入数据之后:");
        singleLink.show();
    }
}

d8c31b9ea79042deb34fb08d602126a3.jpg

4.链表的优缺点

  • 优点:
  • 链表的内存空间不连续。
  • 如果知道要处理节点的前一个位置,则进行插入和删除的复杂度为O(1);
  • 如果不知道要处理节点的前一个位置,则进行插入和删除的复杂度为O(N)。
  • 头插、头删的效率高,时间复杂度是O(1)。
  • 没有空间限制,不会溢出,可以存储很多元素。
  • 缺点:
  • 链表不支持随机访问,查找元素效率低,需要遍历节点,时间复杂度是O(n)。


相关文章
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
300 4
|
存储 Python
Python 实现单向链表,和单向链表的反转
链表是一种数据结构,每个节点存储相邻节点的位置信息。单链表中的节点仅存储下一节点的位置。通过Python实现单链表,定义`ListNode`类并关联节点可创建链表。例如,创建A-&gt;B-&gt;C的链表后,可通过反转函数`reverse`将链表反转为CBA。代码展示了如何实现和操作单链表。
321 6
Python 实现单向链表,和单向链表的反转
|
NoSQL 算法 安全
Redis原理—1.Redis数据结构
本文介绍了Redis 的主要数据结构及应用。
Redis原理—1.Redis数据结构
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
511 30
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
748 25
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
620 5
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
498 5
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
1511 4
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
409 0

热门文章

最新文章

下一篇
开通oss服务