单链表常见操作图文详解

单链表常见操作图文详解https://blog.csdn.net/fanyun_01/article/details/79831877

 单链表的最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能。

     单链表分为两种:有头链表和无头链表。

     无头单链表,也就是phead一只是一个指针,指向链表的第一个节点。

     

带头节点的单链表:只不过头结点的data不保存信息。

//构建一个节点

 
  1. typedef struct Node

  2. {

  3. DataType data;

  4. struct Node *next;

  5.  
  6. }Node,*PHead;

 
  1. //1.初始化单链表

  2. void InitListNode(PNode *pHead)

  3. {

  4. assert(pHead);

  5. *pHead = NULL;

  6. }

 
  1. //2.构建一个结点

  2. PNode BuyNode(DataType _data)

  3. {

  4. PNode node = (PNode)malloc(sizeof(Node));

  5. if (node)

  6. {

  7. node->data = _data;

  8. node->next = NULL;

  9. }

  10. return node;

  11. }

 
  1. /*3.尾插 考虑因素:链表为空时,直接让phead指向新节点即可。 链表不空时,遍历一遍链表,找到最后一个链表,连接在最后一个链表的后面即可。 */

  2. void PushBack(PNode *pHead,DataType _data)

  3. {

  4. assert(pHead);

  5. PNode newNode = BuyNode(_data);

  6. if (NULL == (*pHead))

  7. {

  8. *pHead = newNode;

  9. return ;

  10. }

  11. PNode pCur = *pHead;

  12. while (pCur->next)

  13. {

  14. pCur = pCur->next;

  15. }

  16. pCur->next = newNode;

  17. }

尾插图解:

 
  1. /*4.尾删 考虑因素:链表为空时,直接返回

  2. 链表中只有一个结点时,free这个节点,并将phead置空 链表中有多个节点时,遍历一遍链表,找到最后一个节点(pCur->next == NULL),并且保存最后一个节点的前一个节点的信息 */

  3. void PopBack(PNode *pHead)

  4. {

  5. assert(pHead);

  6. if (NULL == (*pHead))

  7. {

  8. return ;

  9. }

  10. else if (NULL == (*pHead)->next)

  11. {

  12. free(*pHead);

  13. *pHead = NULL;

  14. }

  15. else

  16. {

  17. PNode pCur = *pHead;

  18. PNode prev = pCur;

  19. while (pCur->next)

  20. {

  21. prev = pCur;

  22. pCur = pCur->next;

  23. }

  24. free(pCur);

  25. prev ->next = NULL;

  26. }

  27. }

尾删图解:

 
  1. /*5.头插 考虑因素: 链表为空时:直接让phead指向新的节点即可。 当链表有一个节点或者多个节点时: 如图示:*/

  2. void PushFront(PNode *pHead,DataType _data)

  3. {

  4. assert(pHead);

  5. PNode newNode = BuyNode(_data);

  6. if (NULL == (*pHead))

  7. {

  8. *pHead = newNode;

  9. }

  10. else

  11. {

  12. if (newNode)

  13. {

  14. newNode->next = *pHead;

  15. *pHead = newNode;

  16. }

  17. }

  18. }

头插示意:

 

 
  1. /*6.头删 考虑因素: 链表为空时:直接返回,不需要删除 链表不为空时:当只有一个节点时:free掉这个节点,并将phead置空。 当有多个节点时:如图示 分析可知:有一个节点和有多个节点可以使用相同的逻辑*/

  2. void PopFront(PNode *pHead)

  3. {

  4. assert(pHead);

  5. if (NULL == (*pHead))

  6. {

  7. return ;

  8. }

  9. PNode pDel = *pHead;

  10. *pHead = (*pHead)->next;

  11. free(pDel);

  12. }

头删图解:

 
  1. /*7.逆序打印单链表(递归): */

  2. void printFromTailToFront(PNode pHead)

  3. {

  4. if (pHead)

  5. {

  6. printFromTailToFront(pHead->next);

  7. printf("%d->",pHead->data);

  8. }

  9. }

 
  1. /*8.查找一个值为data的节点,如果存在,返回所在位置,否则,返回NULL

  2. 只需要遍历一遍链表即可。 */

  3. PNode Find(PNode pHead, DataType _data)

  4. {

  5. if (NULL == pHead)

  6. {

  7. return NULL;

  8. }

  9. PNode pCur = pHead;

  10. while (pCur)

  11. {

  12. if (pCur->data == _data)

  13. {

  14. return pCur;

  15. }

  16. pCur = pCur->next;

  17. }

  18. return NULL;

  19. }

  20. //插入一个节点

  21. void InsertNode(PNode pos,DataType _data)

  22. {

  23. if (pos)

  24. {

  25. PNode newNode = BuyNode(_data);

  26. if (newNode)

  27. {

  28. newNode->next = pos->next;

  29. pos->next = newNode;

  30. }

  31. }

  32. }

 
  1. /*9.插入一个节点(由于是单链表,所以只能插在pos位置的后面) 需考虑的因素: ①检查参数(链表是否存在,pos位置是否为空) ②当pos位置不空时:如图示*/

  2. void InsertNode(PNode pos,DataType _data)

  3. {

  4. if (pos)

  5. {

  6. PNode newNode = BuyNode(_data);

  7. if (newNode)

  8. {

  9. newNode->next = pos->next;

  10. pos->next = newNode;

  11. }

  12. }

  13. }

插入一个节点图解:

 
  1. *10.删除pos位置上的一个节点: 需要考虑的因素: ①链表为空和pos为空,直接返回

  2. ②pos不为空且pos为1时,这时就可以转化为删除第一个节点,操作步骤同上面的头删

  3. ③当pos不是第一个节点时,分析如图示:*/

  4. void Erase(PNode* pHead, PNode pos)

  5. {

  6. assert(pHead);

  7. if ((NULL == (*pHead)) && (NULL == pos))

  8. {

  9. return ;

  10. }

  11. if((*pHead) == pos)

  12. {

  13. *pHead = pos->next;

  14. free(pos);

  15. }

  16. else

  17. {

  18. PNode pCur = *pHead;

  19. while (pCur ->next != pos)

  20. {

  21. pCur = pCur->next;

  22. }

  23. pCur->next = pos->next;

  24. free(pos);

  25. }

  26. }

删除pos位置结点图解:

 
  1. /*11.删除单链表中值为_data的节点*/

  2. void Remove(PNode* pHead, DataType _data)

  3. {

  4. assert(pHead);

  5. Erase(pHead, Find(*pHead,_data));

  6. }

 
  1. /*12.删除单链表中所有值为_data的节点:

  2. 需考虑: ①第一个节点的值是_data,因为删除第一个节点需要修改phead的值,所以需要单独处理第一个节点的值是_data的时候。

  3. 删除第一个节点就是上面所说的头删。

  4. ②如果第一个节点的值不是_data,直接处理即可。 下面处理第一个值不是_data(这里的_data为2)的情况:*/

  5. void RemoveAll(PNode *pHead, DataType _data)

  6. {

  7. assert(pHead);

  8. if (NULL == (*pHead))

  9. {

  10. return ;

  11. }

  12. PNode pDel = *pHead;

  13. if ((*pHead)->data == _data)

  14. {

  15. *pHead = (*pHead)->next;

  16. free(pDel);

  17. }

  18. PNode pCur = *pHead;

  19. PNode prev = pCur;

  20. while (pCur)

  21. {

  22. if (pCur->data == _data)

  23. {

  24. prev->next = pCur->next;

  25. free(pCur);

  26. pCur = prev->next;

  27. }

  28. else

  29. {

  30. prev = pCur;

  31. pCur = pCur->next;

  32. }

  33. }

  34. }

删除单链表中所有值为_data的结点图解:

 
  1. /*13.打印单链表:*/

  2. void printList(PNode phead)

  3. {

  4. PNode pCur = phead;

  5. while (pCur)

  6. {

  7. printf("%d ",pCur->data);

  8. pCur = pCur->next;

  9. }

  10. printf("\n");

  11. }

 
  1. /*14.得到单链表中节点的个数: */

  2. size_t Size(PNode pHead)

  3. {

  4. size_t count = 0;

  5. while (pHead)

  6. {

  7. pHead = pHead->next;

  8. count++;

  9. }

  10. return count;

  11. }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值