鱼C论坛

 找回密码
 立即注册
查看: 2296|回复: 0

[学习笔记] 022+-链表基础及基本操作

[复制链接]
发表于 2018-8-25 10:38:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2018-9-23 16:10 编辑

1、链表基本概念
链表:是一种物理存储单元上非连续的存储结构,由一系列结点(链表中每一个元素称为结点)组成,结点动态生成,结点与结点之间通过指针链接。
                每个结点包括两个部分:一部分是存储数据元素的数据域,另一部分是存储下一个结点地址的指针域。
链表的特点:
        1 链表是一种常用的数据结构,它通过指针将一些列数据结点,连接成一个数据链。相对于数组,链表具有更好的动态性。
        2 数据域用来存储数据,指针域用于建立与下一个结点的联系。
        3 建立链表时无需预先知道数据总量的,可以随机的分配空间,可以高效的在链表中的任意位置实时插入或删除数据。
        4 链表的开销,主要是访问顺序性和组织链的空间损失。
约定:
        •头结点、当前结点、前趋结点、后继结点  新建结点
        •pHead、pCurrent、 pPrior、    pNext、     pMalloc
链表编程关键点:
        1、指针指向谁,就把谁的地址赋给指针
        2、辅助指针变量&操作逻辑的关系
2、静态链表
        手工依次为各结点建立指向关系,不能动态增加或减少结点,应用范围小。
  1. struct AdvTeacher
  2. {
  3.         char name[64];
  4.         int age;
  5.         struct AdvTeacher *next;
  6. };
  7.         struct AdvTeacher t1, t2, t3;
  8.         struct AdvTeacher *p;

  9.         t1.age = 10;
  10.         t2.age = 20;
  11.         t3.age = 30;

  12.         t1.next = &t2;  //建立结点之间的指向
  13.         t2.next = &t3;
  14.         t3.next = NULL;
  15.         //遍历链表
  16.         while (p)
  17.         {
  18.                 printf("age:%d\n", p->age);
  19.                 p = p->next;
  20.         }
复制代码

3、带头结点的单项链表
360截图20180825104451905.jpg

        头结点作为链表的开始,第一个结点为业务结点的开始,在进行接口的封装和设计时,链表的对外属性只有指向头结点的指针,其余的操作通过封装好的函数进行。
1.创建链表
        创建链表的头结点,需要在函数内申请内存空间,返回内存空间的首地址(指针函数,二级指针做输出)。
2.循环打印链表
        通过辅助指针记录当前位置,在链表中循环。
3. 指定结点前插入结点,如果没找到指定结点插到最后
        建立要插入的结点,建立两个辅助指针变量,一个指向当前结点,一个指向当前结点的前一个结点,循环每个结点,如果找到指定结点break,最后新结点链到当前结点,前一个结点链到新结点。
4.删除指定的结点
        循环每个结点,找到指定结点后删除并返回。
5.链表的逆置操作
06链表逆置操作和辅助指针变量之间关系.jpg

        1.当链表只有头结点或只有一个业务结点不需要逆置,直接返回即可。
        2.准备环境:p保存第一个结点,q保存第二个结点
        3.从第二个结点开始操作,先缓存q的下一个结点,然后逆置(让第二个结点指向第一个结点),然后p,q各向后移一个对第三个结点做同样操作,知道q的指向NULL.
        4.最后把原先的第一个结点指向NULL,头结点指向p即可。
示例代码:
  1. #include "stdlib.h"
  2. #include "stdio.h"
  3. #include "string.h"
  4. #define _CRT_SECURE_NO_WARNINGS

  5. typedef struct Node
  6. {
  7.         int data;
  8.         struct Node *pNext;
  9. }SLIST;

  10. SLIST *Creat_SList()
  11. {
  12.         int data = 0;

  13.         // 1建立头结点并初始化
  14.         SLIST *pHead = NULL, *pm = NULL, *pCur = NULL;
  15.         pHead = (SLIST*)malloc(sizeof(SLIST));
  16.         if (pHead == NULL)
  17.         {
  18.                 return -1;
  19.         }
  20.         pHead->data = 0;
  21.         pHead->pNext = NULL;
  22.         pCur = pHead;

  23.         // 2循环建立结点,结点中的数据域由键盘输入
  24.         printf("\n Please enter the data of node(-1:quit):");
  25.         scanf("%d", &data);

  26.         while (data != -1)
  27.         {
  28.                 // 不断的malloc新结点, 并为数据域赋值
  29.                 pm = (SLIST*)malloc(sizeof(SLIST));
  30.                 if (pm == NULL)
  31.                 {
  32.                         SList_Destory(pHead);
  33.                         return NULL;
  34.                 }
  35.                 pm->data = data;
  36.                 pm->pNext = NULL;

  37.                 // 新结点加入链表
  38.                 pCur->pNext = pm;
  39.                 pCur = pm;

  40.                 printf("\n Please enter the data of node(-1:quit):");
  41.                 scanf("%d", &data);
  42.         }

  43.         return pHead;2.
  44. }
  45. //打印链表中的每一个值
  46. int SList_Print(SLIST *pHead)
  47. {
  48.         SLIST *pCur = NULL;
  49.         if (pHead == NULL)
  50.         {
  51.                 return -1;
  52.         }
  53.         // 准配环境
  54.         pCur = pHead->pNext;
  55.         printf("\nBegin   ");
  56.         while (pCur)
  57.         {
  58.                 printf("%d ", pCur->data);
  59.                 pCur = pCur->pNext;
  60.         }
  61.         printf("End  \n ");

  62. }

  63. // 在结点数值为x的前面插入y,如果没找到加到最后
  64. int SList_NodeInsert(SLIST *pHead, int x, int y)
  65. {
  66.         SLIST *pCur = pHead, *pPre = NULL, *pTemp = NULL;
  67.         if (pHead == NULL)
  68.         {
  69.                 return -1;
  70.         }
  71.         pTemp = (SLIST*)malloc(sizeof(SLIST));
  72.         if (pTemp == NULL)
  73.         {
  74.                 return -2;
  75.         }
  76.         pTemp->data = y;
  77.         while (pCur)   // 查找值为x结点的前一个结点
  78.         {
  79.                 if (pCur->data == x)
  80.                 {
  81.                         break;
  82.                 }
  83.                 pPre = pCur;
  84.                 pCur = pCur->pNext;
  85.         }
  86.         // 新结点链接到后继结点
  87.         pTemp->pNext = pPre->pNext;
  88.         // 让前驱结点链接到pTemp
  89.         pPre->pNext = pTemp;

  90.         return 0;
  91. }

  92. // 删除值为y的结点,如果不存在则打印删除结点不存在
  93. int SList_NodeDel(SLIST *pHead, int y)
  94. {
  95.         SLIST *pCur = pHead, *pPre = NULL;
  96.         if (pHead == NULL)
  97.         {
  98.                 return -1;
  99.         }
  100.         while (pCur)
  101.         {
  102.                 if (pCur->data == y)
  103.                 {
  104.                         pPre->pNext = pCur->pNext;
  105.                         free(pCur);
  106.                         return 0;
  107.                 }
  108.                 pPre = pCur;
  109.                 pCur = pCur->pNext;
  110.         }
  111.         printf("值为%d结点不存在!\n", y);

  112. }

  113. // 链表逆置操作   //从第二个结点开始逆置
  114. int SList_revse(SLIST *pHead)
  115. {
  116.         SLIST *p = NULL, *q = NULL, *t = NULL;
  117.         if (pHead == NULL)
  118.         {
  119.                 return -1;
  120.         }
  121.         if (pHead->pNext == NULL || pHead->pNext->pNext == NULL)
  122.         {
  123.                 return 0;
  124.         }
  125.         // 准备环境
  126.         p = pHead->pNext;
  127.         q = pHead->pNext->pNext;
  128.         while (q != NULL)
  129.         {
  130.                 //1. 逆置之前做个缓存
  131.                 t = q->pNext;
  132.                 //2.开始逆置
  133.                 q->pNext = p;
  134.                 //3.p,q分别后移
  135.                 p = q;
  136.                 q = t;
  137.         }

  138.         // 扫尾工作
  139.         pHead->pNext->pNext = NULL;
  140.         pHead->pNext = p;
  141.         return 0;

  142. }

  143. // 销毁整个链表
  144. int SList_Destory(SLIST *pHead)
  145. {
  146.         SLIST *pCur = pHead, *pTemp = NULL;
  147.         if (pHead == NULL)
  148.         {
  149.                 return -1;
  150.         }
  151.         while (pCur)
  152.         {
  153.                 // 缓存后继结点
  154.                 pTemp = pCur->pNext;
  155.                 // 删除当前结点
  156.                 free(pCur);
  157.                 // 当前结点下移
  158.                 pCur = pTemp;

  159.         }
  160.         return 0;
  161. }

  162. void main()
  163. {
  164.         SLIST *pHead = NULL;
  165.         pHead = Creat_SList();
  166.         SList_Print(pHead);
  167.         SList_NodeInsert(pHead, 20, 19);
  168.         SList_Print(pHead);
  169.         SList_NodeDel(pHead, 20);
  170.         SList_Print(pHead);
  171.         SList_revse(pHead);
  172.         SList_Print(pHead);
  173.         SList_Destory(pHead);
  174.         system("pause");
  175. }
复制代码


本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-22 04:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表