当前位置:   article > 正文

无头单向链表_无头链表

无头链表

目录

一、无头单向链表概念和结构

二、无头单向链表的接口实现

三、无头单向链表的优缺点


一、无头单向链表概念和结构

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

 结构示意图:由前一个链表中的指针指向下一个链表的地址,在逻辑上是连续的。

二、无头单向链表的接口实现

  1. #include <stdio.h>
  2. #include <assert.h>
  3. #include <stdlib.h>
  4. typedef int SLTDataType;
  5. typedef struct SListNode
  6. {
  7. SLTDataType data;
  8. struct SListNode* next;
  9. }SLTNode;
  • 创建新结点

顺序表是按需创造和销毁结点,每当想存储一个数据的时候,就malloc一个新结点

  1. //创建新节点
  2. SLTNode* BuySListNode(SLTDataType x)
  3. {
  4. SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
  5. assert(newnode);
  6. newnode->data = x;
  7. newnode->next = NULL;
  8. return newnode;
  9. }

创造新节点,直接将新节点包含的指针指向原来的头结点,将新节点的地址作为之前的头结点。

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

创造一个新的结点,判断原来的头是否为空,为空,将新创造的结点作为新的头。不为空就找到尾结点将尾结点包含的指针指向新创建的结点地址。

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

判断链表是否为空,不为空,将头节点的地址修改成头节点指向的下一个结点的地址,释放之前的头结点。

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

判断链表是否为空,不为空,找到尾结点,将尾结点之前的结点指向下一个结点的指针置为空,释放掉尾结点。

  1. //尾删
  2. void SListPopBack(SLTNode** pphead)
  3. {
  4. assert(*pphead && pphead);
  5. if ((*pphead)->next == NULL)
  6. {
  7. free(*pphead);
  8. *pphead = NULL;
  9. }
  10. else
  11. {
  12. SLTNode* tailPrev = NULL;//tailPrev 结尾之前
  13. SLTNode* tail = *pphead;
  14. while (tail->next != NULL)
  15. {
  16. tailPrev = tail;
  17. tail = tail->next;
  18. }
  19. tailPrev->next = NULL;
  20. free(tail);
  21. tail = NULL;
  22. }
  23. }

找到pos位置,保存pos之前的结点的地址,创建新结点,pos之前的结点中指向下一个结点指针指向新节点,新节点中指向下一个结点指针指向pos

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

找到pos之前的结点的地址,pos之前的结点中指向下一个结点的指针指向pos结点中指向下一个结点的地址,释放pos。

  1. //删除pos位置的值
  2. void SListErase(SLTNode** pphead, SLTNode* pos)
  3. {
  4. assert(pos && pphead);
  5. if (pos == *pphead)
  6. {
  7. *pphead = pos->next;
  8. }
  9. else
  10. {
  11. SLTNode* prve = *pphead;
  12. while (prve->next != pos)
  13. {
  14. prve = prve->next;
  15. }
  16. prve->next = pos->next;
  17. }
  18. free(pos);
  19. pos = NULL;
  20. }
  1. //查找
  2. SLTNode* SListFind(SLTNode* phead, SLTDataType x)
  3. {
  4. assert(phead);
  5. SLTNode* cru = phead;
  6. while (cru)
  7. {
  8. if (cru->data == x)
  9. {
  10. return cru;
  11. }
  12. else
  13. {
  14. cru = cru->next;
  15. }
  16. }
  17. return NULL;
  18. }
  1. //打印链表
  2. void SListPrint(SLTNode* phead)
  3. {
  4. SLTNode* cru = phead;
  5. while (cru != NULL)
  6. {
  7. printf("%d->", cru->data);
  8. cru = cru->next;
  9. }
  10. printf("NULL\n");
  11. }
  1. void SListDestory(SLTNode** pphead)
  2. {
  3. //使用尾删
  4. SListPopBack(pphead);
  5. }

三、无头单向链表的优缺点

优点:
1. 无头单向链表可以轻松地插入或删除链表的头部和尾部,因为它不需要像有头链表一样先找到头部节点。
2. 在某些情况下,无头单向链表可以在空间上更加高效,因为它不需要额外的头节点。

缺点:
1. 在访问链表中的任何节点之前需要检查链表是否为空,因为没有头节点来作为起点。
2. 在查找链表中的任何节点时,必须从头开始遍历,因为没有头节点可以直接引用链表的起点。这可能会导致性能下降,特别是对于较大的链表来说。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/767430
推荐阅读
相关标签
  

闽ICP备14008679号