• 【数据结构】链表--单链表


    目录

    一 概念及结构

    二 单链表的实现

    1 包含接口(SList.h)

    2 打印和创造节点(扩容)(SList.c)

    3 尾插(SList.c)

    4 头插(SList.c)

    5 尾删(SList.c) 

    6 头删(SList.c)

    7 在pos前插入x(SList.c)

    8 在pos后插入x(SList.c)

    9 删除pos 位置(SList.c)

    10 删除pos后一个位置(SList.c)

    11 销毁 (SList.c) 

    12 测试 (Test.c) 


    一 概念及结构

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

    1 链式结构在逻辑上是连续的, 但是在物理上不一定连续

    2 现实中的结点一般都是从堆中申请出来的

    3 从堆上申请的空间 是按照一定的策略来分配的 再次申请的空间可能连续 也可能不连续

    链表的分类:

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

    2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都 是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带 来很多优势,实现反而简单了,后面我们代码实现了就知道了

    单链表的实现

    1 包含接口(SList.h)

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. typedef int SLTDataType;
    6. typedef struct SListNode
    7. {
    8. SLTDataType data;
    9. struct SListNode* next;
    10. }SLTNode;
    11. //打印
    12. void SLTPrint(SLTNode* phead);
    13. //扩容
    14. SLTNode* BuySListNode(SLTDataType x);
    15. //尾插头插
    16. void SLTPushBack(SLTNode** pphead, SLTDataType x);
    17. void SLTPushFront(SLTNode** pphead, SLTDataType x);
    18. //尾删头删
    19. void SLTPopBack(SLTNode** pphead);
    20. void SLTPopFront(SLTNode** pphead);
    21. //找位置
    22. SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
    23. // 在pos之前插入x
    24. void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
    25. // 在pos以后插入x
    26. void SLTInsertAfter(SLTNode* pos, SLTDataType x);
    27. // 删除pos位置
    28. void SLTErase(SLTNode** pphead, SLTNode* pos);
    29. // 删除pos的后一个位置
    30. void SLTInsertAfter(SLTNode* pos);

    2 打印和创造节点(扩容)(SList.c)

    1. #include"SList.h"
    2. //打印
    3. void SLTPrint(SLTNode* phead)
    4. {
    5. SLTNode* cur = phead;
    6. while (cur)
    7. {
    8. printf("%d->", cur->data);
    9. cur = cur->next;
    10. }
    11. printf("NULL\n");
    12. }
    13. //扩容
    14. SLTNode* BuySListNode(SLTDataType x)
    15. {
    16. SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    17. if (newnode == NULL)
    18. {
    19. perror("malloc failed");
    20. exit(-1);
    21. }
    22. newnode->data = x;
    23. newnode->next = NULL;
    24. return newnode;
    25. }

    3 尾插(SList.c)

    1. //尾插
    2. void SLTPushBack(SLTNode** pphead, SLTDataType x)
    3. {
    4. SLTNode* newnode = BuySListNode(x);
    5. if (*pphead == NULL)
    6. {
    7. *pphead = newnode;
    8. }
    9. else
    10. {
    11. SLTNode* tail = *pphead;
    12. while (tail->next != NULL)
    13. {
    14. tail = tail->next;
    15. }
    16. tail->next = newnode;
    17. }
    18. }

    总结:改变结构体用结构体指针 改变结构体二级指针

    4 头插(SList.c)

    1. //头插
    2. void SLTPushFront(SLTNode** pphead, SLTDataType x)
    3. {
    4. SLTNode* newnode = BuySListNode(x);
    5. newnode->next = *pphead;
    6. *pphead = newnode;
    7. }

    5 尾删(SList.c) 

    1. //尾删
    2. void SLTPopBack(SLTNode** pphead)
    3. {
    4. //空
    5. assert(*pphead);
    6. //一个节点
    7. if ((*pphead)->next == NULL)
    8. {
    9. free(*pphead);
    10. *pphead = NULL;
    11. }
    12. else
    13. {
    14. SLTNode* tail = *pphead;
    15. SLTNode* tailPrev = *pphead;
    16. while (tail->next)
    17. {
    18. tailPrev = tail;
    19. tail = tail->next;
    20. }
    21. free(tail);
    22. tailPrev->next = NULL;
    23. }
    24. }

     

    6 头删(SList.c)

    1. //头删
    2. void SLTPopFront(SLTNode** pphead)
    3. {
    4. assert(*pphead);
    5. SLTNode* newhead = (*pphead)->next;
    6. free(*pphead);
    7. *pphead = newhead;
    8. }

    7 在pos前插入x(SList.c)

    1. // 在pos之前插入x
    2. void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
    3. {
    4. assert(*pphead);
    5. assert(pos);
    6. if (pos == 0)
    7. {
    8. SLTPushFront(*pphead, x);
    9. }
    10. else
    11. {
    12. SLTNode* newnode = BuySListNode(x);
    13. SLTNode* prev = *pphead;
    14. while (prev->next != pos)
    15. {
    16. prev = prev->next;
    17. }
    18. prev->next = newnode;
    19. newnode->next = pos;
    20. }
    21. }

    8 在pos后插入x(SList.c)

    1. // 在pos以后插入x
    2. void SLTInsertAfter(SLTNode* pos, SLTDataType x)
    3. {
    4. assert(pos);
    5. SLTNode* newnode = BuySListNode(x);
    6. newnode->next = pos->next;
    7. pos->next = newnode;
    8. }

     

    9 删除pos 位置(SList.c)

    1. // 删除pos位置
    2. void SLTErase(SLTNode** pphead, SLTNode* pos)
    3. {
    4. assert(*pphead);
    5. assert(pos);
    6. if (pos == *pphead)
    7. {
    8. SLTPopFront(pphead);
    9. }
    10. else
    11. {
    12. SLTNode* prev = *pphead;
    13. while (prev->next != pos)
    14. {
    15. prev = prev->next;
    16. }
    17. prev->next = pos->next;
    18. free(pos);
    19. }
    20. }

     

    10 删除pos后一个位置(SList.c)

    1. // 删除pos的后一个位置
    2. void SLTEraseAfter(SLTNode* pos)
    3. {
    4. assert(pos);
    5. assert(pos->next);//检查pos是否是尾节点
    6. SLTNode* posNext = pos->next;
    7. pos->next = posNext->next;
    8. free(posNext);
    9. posNext = NULL;
    10. }

    11 销毁 (SList.c) 

    1. //销毁
    2. void SLTDestroy(SLTNode** pphead)
    3. {
    4. assert(pphead);
    5. SLTNode* cur = *pphead;
    6. while (cur)
    7. {
    8. SLTNode* next = cur->next;
    9. free(cur);
    10. cur = next;
    11. }
    12. *pphead = NULL;
    13. }

    12 测试 (Test.c) 

    1. void TestSList5()
    2. {
    3. SLTNode* plist = NULL;
    4. SLTPushBack(&plist, 1);//传地址 才能改变结构体
    5. SLTPushBack(&plist, 2);
    6. SLTPushBack(&plist, 3);
    7. SLTPushBack(&plist, 4);
    8. SLTPushBack(&plist, 5);
    9. SLTPushBack(&plist, 6);
    10. SLTPrint(plist);
    11. SLTPushFront(&plist, 40);
    12. SLTPrint(plist);
    13. SLTPopBack(&plist);
    14. SLTPrint(plist);
    15. SLTPopFront(&plist);
    16. SLTPrint(plist);
    17. int x = 0;
    18. scanf("%d", &x);
    19. SLTNode* pos = SLTFind(plist, x);
    20. SLTInsertAfter(pos, 50);
    21. SLTInsert(&plist, pos, 40);
    22. SLTPrint(plist);
    23. SLTEraseAfter(pos);
    24. SLTPrint(plist);
    25. SLTErase(&plist, pos);
    26. SLTPrint(plist);
    27. }
    28. int main()
    29. {
    30. TestSList5();
    31. return 0;
    32. }

     

  • 相关阅读:
    java中SimpleDateFormat解析日期格式的问题
    深度学习笔记_4、CNN卷积神经网络+全连接神经网络解决MNIST数据
    【MATLAB源码-第80期】基于蚯蚓优化算法(EOA)的无人机三维路径规划,输出做短路径图和适应度曲线
    [附源码]计算机毕业设计车源后台管理系统
    练[极客大挑战 2019]BuyFlag
    pytest运行时参数说明,pytest详解,pytest.ini详解
    jetsonTX2 nx配置yolov5和D435I相机,完整步骤
    国产分布式数据库sequoiadb的前景如何?
    【数据库原理及应用】——事务并发控制和恢复技术(学习笔记)
    【数学建模】 复杂网络与图论模型
  • 原文地址:https://blog.csdn.net/yf214wxy/article/details/132986198