• 线性表——顺序表和链表


    目录

    一、线性表

    二、顺序表

    1.顺序表的概念

    2.静态与动态顺序表

    3.动态顺序表的代码实现

    三、链表

    1.概念及结构概念

    2.链表的种类

    4.特殊链表的实现

    (1)无头单向非循环链表

    C语言代码实现:(1条消息) 无头单向非循环链表_聪明的骑士的博客-CSDN博客

    (2)带头双向循环链表

    四、顺序表和链表的区别和联系


    一、线性表

    线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构。

    常见的线性表:顺序表、链表、栈、队列、字符串...

    线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

    二、顺序表

    1.顺序表的概念

    简单地说,顺序表就是数组。

    2.静态与动态顺序表

    1. //顺序表的静态存储
    2. #define N 100
    3. typedef int SLDataType;
    4. typedef struct SeqList
    5. {
    6. SLDataType array[N]; //一个定长数组
    7. size_t size; //有效数据的个数
    8. }SeqList;
    9. // 顺序表的动态存储
    10. typedef struct SeqList
    11. {
    12. SLDataType* array; //指向动态开辟的数组
    13. size_t size; //有效数据个数
    14. size_t capicity;//容量空间的大小
    15. }SeqList;

    静态的顺序表一次性开辟空间,不可扩容;动态顺序表可以根据数据的储存在堆区扩容。

    3.动态顺序表的代码实现

    1. #define TYPE int
    2. struct SeqList
    3. {
    4. TYPE* SL;
    5. int volume;
    6. int size;
    7. };
    8. typedef struct SeqList SList;
    9. //初始化
    10. void InitSeqlist(SList* p);
    11. //扩容
    12. void enlarge(SList* p);
    13. //打印
    14. void print(SList* p);
    15. //销毁
    16. void destory(SList* p);
    17. //对顺序表实现增删查改的函数
    18. //增加元素
    19. void Seqlist_front_push(SList* p, TYPE a);//前增
    20. void Seqlist_back_push(SList* p, TYPE a); //后增
    21. //减少元素
    22. void Seqlist_front_pop(SList* p); //前减
    23. void Seqlist_back_pop(SList* p);//后减
    24. //查找对应下标的元素,没有找到就返回-1
    25. int Seqlist_search_element(SList* p,TYPE a);
    26. //修改对应下标的元素
    27. void Seqlist_modify_element(SList* p, size_t pos, TYPE b);
    28. // 顺序表在pos位置插入a
    29. void SLInsert(SList* p, size_t pos, TYPE a);
    30. // 顺序表删除pos位置的值
    31. void SLErase(SList* p, size_t pos);

    包括了顺序表的增删查改的操作,下面是代码实现:

    (4条消息) 动态顺序表的代码实现_聪明的骑士的博客-CSDN博客

    三、链表

    1.概念及结构概念

    链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

    就像寻宝游戏中的线索一样,你有了一条线索,然后沿着这条线索寻找,你会找到下一条线索,沿着找到的条线索寻找,你又会找到下一条线索,这样层层递进最后就能找到宝物,所有的线索也都被串联起来了。

    你如果在上一层的数据中存放下一层的信息,那么这一层层的信息就可以不断向下寻找,我们的数据就也被串联起来了,这就是一种链表的简单概括。

    链表的思想,就是结构体的自引用的应用。

    2.链表的种类

    实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

    (1)单向、双向

    单向链表只存在一个next指针,只支持向后访问。

    双向链表有prev和next指针,可以向后或向前访问。

    (2)带头、不带头

    带头指带哨兵卫的头节点,此时我们的头节点不再存储有效数据,只存储地址下一个位置作为头节点。通过哨兵卫就可以避免二级指针并简化代码。

    (3)循环、非循环

    循环的链表尾节点指向头节点,反之亦然,这样就做到了头部和尾部的快速访问。

    这三个二选一的选择题经过组合就是一种类型。

    4.特殊链表的实现

    我们实际中最常用还是两种结构:无头单向非循环链表和带头双向循环链表

    (1)无头单向非循环链表

    结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

    1. #define TYPE int
    2. typedef struct SListNode
    3. {
    4. TYPE data;
    5. struct SListNode* next;
    6. }SLNode;
    7. //动态申请一个节点
    8. SLNode* BuySListNode(TYPE x);
    9. // 单链表打印
    10. void SListPrint(SLNode* plist);
    11. // 单链表尾插
    12. void SListPushBack(SLNode** pplist,TYPE x);
    13. // 单链表的头插
    14. void SListPushFront(SLNode** pplist, TYPE x);
    15. // 单链表的尾删
    16. void SListPopBack(SLNode** pplist);
    17. // 单链表头删
    18. void SListPopFront(SLNode** pplist);
    19. // 单链表查找
    20. SLNode* SListFind(SLNode* plist, TYPE x);

    C语言代码实现:(1条消息) 无头单向非循环链表_聪明的骑士的博客-CSDN博客

    (2)带头双向循环链表

    结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势。

    1. #define TYPE int
    2. typedef struct DoubleList
    3. {
    4. TYPE* data;
    5. struct DoubleList* prev;
    6. struct DoubleList* next;
    7. }DList;
    8. //初始化双向链表
    9. DList* InitDList(DList* p);
    10. //初始化节点
    11. DList* Buylistnode(TYPE x);
    12. //头插
    13. void DListfrontpush(DList* p, TYPE x);
    14. //尾插
    15. void DListbackpush(DList* p, TYPE x);
    16. //头删
    17. void DListfrontpop(DList* p);
    18. //尾删
    19. void DListbackpop(DList* p);
    20. //判读链表是否为空
    21. bool ListEmpty(DList* p);
    22. //计算大小
    23. size_t ListSize(DList* p);
    24. //寻找元素
    25. DList* ListFind(DList* p, TYPE x);
    26. // 在pos之前插入
    27. void ListInsert(DList* pos, TYPE x);
    28. // 删除pos位置
    29. void ListErase(DList* pos);
    30. //考虑用一级指针,让调用ListDestory的人置空(保持接口一致性)
    31. void ListDestory(DList* p);
    32. //打印链表
    33. void print(DList* p);

    C语言代码实现:带头双向循环链表_聪明的骑士的博客-CSDN博客

    四、顺序表和链表的区别和联系

    1.顺序表

    优势:空间连续、支持随机访问

    劣势:

    (1)中间或前面部分的插入删除时间复杂度O(N)

    (2)增容的代价比较大。

    2.链表

    劣势:以节点为单位存储,不支持随机访问

    优势:

    (1)任意位置插入删除时间复杂度为O(1)

    (2)没有增容问题,插入一个开辟一个空间。

  • 相关阅读:
    第2-4-2章 规则引擎Drools入门案例-业务规则管理系统-组件化-中台
    一文生成猫眼电影热榜词云
    05.爱芳地产项目小程序全栈项目经验(已上线)
    旅游网站大数据分析 - 数据抓取
    【Java 基础篇】Java Supplier 接口详解
    中国陆地生态系统服务价值空间分布数据集
    chromedp库编写程序
    C语言详细知识点复习(上)
    SpringBoot - @ConditionalOnProperty注解使用详解
    python面向对象(下)
  • 原文地址:https://blog.csdn.net/qq_65285898/article/details/126456180