链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。

作为有强大功能的链表,对他的操作当然有许多,比如:链表的创建,修改,删除,插入,输出,排序,反序,清空链表的元素,求链表的长度等等。

这里在mcu上运行OK:

C文件:

  • Node Pnode;
  • void SListInit(SList* s)
  • {
  •         s->_pHead = NULL;
  • }
  • //构建一个结点
  • PNode BuySListNode(SDataType _data)
  • {
  •     PNode node = (PNode)malloc(sizeof(Node));
  •     if (node)
  •     {
  •          node->_data = _data;
  •          node->_PNext = NULL;
  •     }
  •     return node;
  • }
  • /*
  • 尾插,首先要创建一个新节点,然后判断链表当前是否有节点,若没有,则直接让第一个节点指向新节点,
  • 若有,找到最后一个节点,让他指向新节点
  • */
  • void SListPushBack(SList* s, SDataType data)
  • {
  •          //找链表最后一个节点
  •          PNode pNewNode = BuySListNode(data);
  •          if (s->_pHead == NULL) {//链表没有节点的情况
  •           s->_pHead = pNewNode;
  •          }
  •          else {
  •           PNode pCur = s->_pHead;
  •           while (pCur->_PNext) {
  •            pCur = pCur->_PNext;
  •           }
  •           //让最后一个节点指向新节点
  •           pCur->_PNext = pNewNode;
  •          }
  • }
  • /*查找某个特征的节点*/
  • PNode SListFind(SList* s, SDataType data)
  • {
  •          PNode pCur = s->_pHead;
  •          while (pCur) {
  •           if (pCur->_data == data) {
  •            return pCur;
  •           }
  •           pCur = pCur->_PNext;
  •          }
  •          return NULL;
  • }
  • /*
  • 删除给定pos位置的节点
  • */
  • void SListErase(SList* s, PNode pos)
  • {
  •          if (pos == NULL || s->_pHead == NULL) {
  •           return;
  •          }
  •          if (pos== s->_pHead) {
  •           s->_pHead = pos->_PNext;
  •          }
  •          else {
  •           PNode pPrePos = s->_pHead;
  •           while (pPrePos&&pPrePos->_PNext != pos) {
  •            pPrePos = pPrePos->_PNext;
  •           }
  •           pPrePos->_PNext = pos->_PNext;
  •          }
  •          free(pos);
  • }
  • //获取链表有效节点的个数
  • int SListSize(SList* s)
  • {            
  •          int count = 0;
  •          PNode pCur = s->_pHead;
  •          while (pCur) {
  •           count++;
  •           pCur = pCur->_PNext;
  •          }
  •          return count;
  • }
  • //检测链表是否为空
  • int SListEmpty(SList* s)
  • {                    
  •         if (s->_pHead == NULL)
  •         {
  •           return -1;
  •         }
  •          return 0;
  • }
  • //清空链表
  • void SListClear(SList* s)
  • {            
  • if (s->_pHead == NULL) {
  •   return;
  • }
  • PNode pCur = s->_pHead;
  • while (pCur->_PNext) {    //循环清空链表中的节点
  •   PNode Tmp = pCur->_PNext;
  •   free(pCur);
  •   pCur = Tmp;
  • }
  • if (pCur) {      //清空最后一个节点
  •   free(pCur);
  •   pCur = NULL;
  • }
  • }
  • //销毁链表
  • void SListDestroy(SList* s)
  • {           
  • if (s->_pHead == NULL) {
  •   free(s->_pHead);
  •   return;
  • }
  • while (s->_pHead) {   
  •   PNode Tmp = s->_pHead->_PNext;
  •   free(s->_pHead);
  •   s->_pHead = Tmp;
  • }
  • }
  • //打印链表
  • void SListPrint(SList* s)
  • {            
  • PNode pCur = s->_pHead;
  • while (pCur) {
  •   printf("%d--->", pCur->_data);
  •   pCur = pCur->_PNext;
  • }
  • printf("\n");
  • }
  • /**********************Tests**************************************
  • void main()
  • {
  • SList s;
  • SListInit(&s);
  • SListPushBack(&s, 1);
  • SListPushBack(&s, 2);
  • SListPushBack(&s, 3);
  • printf("size=%d\n", SListSize(&s));
  • SListPrint(&s);
  • SListInsert(SListFind(&s, 2), 0);
  • SListPrint(&s);
  • SListRemove(&s, 2);
  • SListPrint(&s);
  • system("pause");
  • return;
  • }
  • *****************************************************************/
  • 复制代码

    头文件:

    #include "gpio.h"
  • #include <stdio.h>
  • #include <assert.h>
  • #include <stdlib.h>
  • #include <stddef.h>
  • /*人对象的结构体*/
  • typedef struct User
  • {
  •         uint8_t ID;         /*用户ID*/
  •         uint8_t cup_ID ;
  •         uint8_t locker_index;
  • }stUser;
  • typedef int SDataType;
  • //链表的节点
  • typedef struct SListNode
  • {
  •         SDataType _data;
  •         struct SListNode* _PNext;
  • }Node,*PNode;
  • typedef struct SList       //封装了链表的结构
  • {
  •         PNode _pHead;//指向链表第一个节点
  • }SList;
  • void SListInit(SList*s);//链表的初始化
  • //在链表s最后一个节点后插入一个值为data的节点
  • void SListPushBack(SList* s, SDataType data);
  • //删除链表s最后一个节点
  • void SListPopBack(SList* s);
  • //在链表s第一个节点前插入值为data的节点
  • void SListPushFront(SList* s, SDataType data);
  • //删除链表s的第一个节点
  • void SListPopFront(SList* s);
  • //在链表的pos位置后插入值为data的节点
  • void SListInsert(PNode pos, SDataType data);
  • //删除链表s中pos位置的节点
  • void SListErase(SList* s, PNode pos);
  • // 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL
  • PNode SListFind(SList* s, SDataType data);
  • //移除链表中第一个值为data的元素
  • void SListRemove(SList*s, SDataType data);
  • // 获取链表中有效节点的个数
  • int SListSize(SList* s);
  • // 检测链表是否为空
  • int SListEmpty(SList* s);
  • // 将链表中有效节点清空
  • void SListClear(SList* s);
  • // 销毁链表
  • void SListDestroy(SList* s);
  • //打印链表
  • void SListPrint(SList* s);
  • 复制代码

    微信图片_20201129221837.png