当前位置:   article > 正文

【数据结构】单链表&带头双向循环链表的实现

【数据结构】单链表&带头双向循环链表的实现

一、链表的概念及结构

1.链表的概念

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

2.链表的结构

一般讲的链表包括数据域和指针域:

二、链表的种类

实际中链表的结构非常多样,由以下三组类型自由组合可得8种链表结构:

1.单向、双向:

2.带头、不带头:

3.循环、非循环:

虽然有这么多类型,但我们最长使用的就是以下两种:

在此我们只实现这两种链表

三、单链表的实现

1.自定义链表结点struct SListNode
  1. typedef int SLTDateType;
  2. typedef struct SListNode
  3. {
  4. SLTDateType data;
  5. struct SListNode* next;
  6. }SListNode;
2.链表打印数据SListPrint
  1. //打印
  2. void SListPrint(SListNode* plist)
  3. {
  4. if (plist == NULL)
  5. return;
  6. while (plist)
  7. {
  8. printf("%d->", plist->data);
  9. plist = plist->next;
  10. }
  11. }
3.链表创建结点BuyListNode
  1. //创建节点
  2. SListNode* BuySListNode(SLTDateType x)
  3. {
  4. SListNode* new_node = (SListNode*)malloc(sizeof(SListNode));
  5. if (new_node == NULL)
  6. {
  7. perror("malloc fail");
  8. return NULL;
  9. }
  10. new_node->data = x;
  11. new_node->next = NULL;
  12. return new_node;
  13. }
4.链表尾部插入数据SListPushBack
  1. //尾插
  2. void SListPushBack(SListNode** pplist, SLTDateType x)
  3. {
  4. //无节点
  5. if (*pplist == NULL)
  6. {
  7. (*pplist) = BuySListNode(x);
  8. }
  9. //有节点
  10. SListNode* tail = *pplist;
  11. while (tail->next)
  12. {
  13. tail = tail->next;
  14. }
  15. tail->next = BuySListNode(x);
  16. }
5.链表头部插入数据SListPushFront
  1. //头插
  2. void SListPushFront(SListNode** pplist, SLTDateType x)
  3. {
  4. SListNode* new_node = BuySListNode(x);
  5. new_node->next = *pplist;
  6. *pplist = new_node;
  7. }
6.链表尾部删除数据SListPopBack
  1. //尾删
  2. void SListPopBack(SListNode** pplist)
  3. {
  4. //空链表
  5. if ((*pplist) == NULL)
  6. return;
  7. //一个节点
  8. if ((*pplist)->next == NULL)
  9. {
  10. SListNode* tmp = *pplist;
  11. free(tmp);
  12. tmp = NULL;
  13. }
  14. //多个节点
  15. else
  16. {
  17. SListNode* cur = *pplist;
  18. SListNode* next = cur->next;
  19. //找尾
  20. while (cur->next->next)
  21. {
  22. cur = next;
  23. next = next->next;
  24. }
  25. free(next);
  26. cur->next = NULL;
  27. }
  28. }
7.链表头部删除数据SListPopFront
  1. //头删
  2. void SLPopFront(SListNode** pplist)
  3. {
  4. //没有节点
  5. if ((*pplist) == NULL)
  6. return;
  7. //一个节点
  8. //多个节点
  9. SListNode* tmp = *pplist;
  10. *pplist = (*pplist)->next;
  11. free(tmp);
  12. tmp = NULL;
  13. }
8.链表查找数据
  1. //查找
  2. SListNode* SListFind(SListNode* plist, SLTDateType x)
  3. {
  4. SListNode* cur = plist;
  5. while (cur)
  6. {
  7. if (cur->data == x)
  8. {
  9. return cur;
  10. }
  11. cur = cur->next;
  12. }
  13. return NULL;
  14. }
9.链表在pos位置之后插入数据
  1. // 单链表在pos位置之后插入x
  2. void SListInsertAfter(SListNode* pos, SLTDateType x)
  3. {
  4. SListNode* newnode = BuySListNode(x);
  5. //在非尾节点插入
  6. if (pos->next != NULL)
  7. {
  8. newnode->next = pos->next;
  9. pos->next = newnode;
  10. }
  11. else
  12. {
  13. SListPushBack(&pos, x);
  14. }
  15. }

10.删除pos位置之后的值

  1. // 单链表删除pos位置之后的值
  2. void SListEraseAfter(SListNode* pos)
  3. {
  4. if (pos->next == NULL)
  5. {
  6. printf("erroe");
  7. return;
  8. }
  9. SListNode* del = pos->next;
  10. pos->next = del->next;
  11. free(del);
  12. del = NULL;
  13. }

11.销毁链表

  1. //销毁链表
  2. void SLTDestroy(SListNode** pphead)
  3. {
  4. if (*pphead == NULL)
  5. return;
  6. SListNode* next = (*(pphead))->next;
  7. while (*pphead)
  8. {
  9. //销毁
  10. SListNode* del = *pphead;
  11. free(del);
  12. del = NULL;
  13. //迭代
  14. *pphead = next;
  15. if(next)
  16. next = next->next;
  17. }
  18. }

四.带头双向循环链表的实现

1.自定义链表结点 ListNode

  1. typedef int LTDataType;
  2. typedef struct ListNode
  3. {
  4. LTDataType _data;
  5. struct ListNode* _next;
  6. struct ListNode* _prev;
  7. }ListNode;

2.创建新节点

  1. //创建新节点
  2. ListNode* BuyLTNode(LTDataType x)
  3. {
  4. ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
  5. if (newnode == NULL)
  6. {
  7. perror("malloc fail");
  8. return NULL;
  9. }
  10. newnode->_data = x;
  11. newnode->_next = NULL;
  12. newnode->_prev = NULL;
  13. return newnode;
  14. }

3.创建一个新链表,返回头结点

  1. // 创建返回链表的头结点.
  2. ListNode* ListCreate()
  3. {
  4. ListNode* Phead = BuyLTNode(-1);
  5. Phead->_next = Phead;
  6. Phead->_prev = Phead;
  7. return Phead;
  8. }

4.打印链表

  1. //打印链表
  2. void ListPrint(ListNode* pHead)
  3. {
  4. if (pHead == NULL)
  5. return;
  6. ListNode* cur = pHead->_next;
  7. printf("pHead <=> ");
  8. while (cur!=pHead)
  9. {
  10. printf("%d <=> ", cur->_data);
  11. cur = cur->_next;
  12. }
  13. }

5.在pos之前插入值为x节点

  1. //在pos前插入
  2. void ListInsert(ListNode* pos, LTDataType x)
  3. {
  4. ListNode* pre = pos->_prev;
  5. ListNode* newnode = BuyLTNode(x);
  6. newnode->_next = pos;
  7. pos->_prev = newnode;
  8. pre->_next = newnode;
  9. newnode->_prev = pre;
  10. }

6.尾插

  1. //尾插
  2. void ListPushBack(ListNode* pHead, LTDataType x)
  3. {
  4. ListInsert(pHead, x);
  5. }

7.头插

  1. //头插
  2. void ListPushFront(ListNode* pHead, LTDataType x)
  3. {
  4. ListInsert(pHead->_next, x);
  5. }

8.删除pos位置节点

  1. //删除pos位置的节点
  2. void ListErase(ListNode* pos)
  3. {
  4. ListNode* pre = pos->_prev;
  5. ListNode* next = pos->_next;
  6. free(pos);
  7. pos = NULL;
  8. pre->_next = next;
  9. next->_prev = pre;
  10. }

9.双向链表头删

  1. // 双向链表头删
  2. void ListPopFront(ListNode* pHead)
  3. {
  4. ListErase(pHead->_next);
  5. }

10.双向链表尾删

  1. // 双向链表尾删
  2. void ListPopBack(ListNode* pHead)
  3. {
  4. ListErase(pHead->_prev);
  5. }

11.查找

  1. // 双向链表查找
  2. ListNode* ListFind(ListNode* pHead, LTDataType x)
  3. {
  4. ListNode* cur = pHead->_next;
  5. while (cur != pHead)
  6. {
  7. if (cur->_data == x)
  8. return cur;
  9. cur = cur->_next;
  10. }
  11. return NULL;
  12. }

12.销毁链表

  1. //销毁链表
  2. void ListDestory(ListNode* pHead)
  3. {
  4. ListNode* cur = pHead->_next;
  5. while (cur)
  6. {
  7. ListNode* next = cur->_next;
  8. free(cur);
  9. pHead->_next = next;
  10. cur = next;
  11. }
  12. }

注:带头双向循环链表的头插头删,尾插尾删直接复用了插入删除代码。

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

闽ICP备14008679号