当前位置:   article > 正文

数据结构:双向链表(带头双向循环链表).

数据结构:双向链表(带头双向循环链表).

带头:链表的头节点不存储有效数据

双向:链表结构体中存在两个指针,分别指向链表的前后两个节点

循环:链表的尾节点指向头节点,形成循环

双向链表只有头节点时,该链表为空链表

头节点不能进行删除或修改

  1. //定义双向链表中节点的结构
  2. typedef int LTDataType;
  3. typedef struct ListNode
  4. {
  5. int data;
  6. struct ListNode* prev;
  7. struct ListNode* next;
  8. }LTNode;

一.双向链表的初始化

  1. LTNode* LTBuyNode(LTDataType x)
  2. {
  3. LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
  4. if(newnode == NULL)
  5. {
  6. perror("malloc fail");
  7. exit(1);
  8. }
  9. newnode->data = x;
  10. newnode->next = newnode->prev = newnode;
  11. return newnode;
  12. }
  13. LTNode* LTInit(LTNode** pphead)
  14. {
  15. LTNode* phead = LTBuyNode(-1);//传入-1表示头节点存储的数据无效,-1可以改成任意数字,无实际意义
  16. return phead;
  17. }

二.双向链表的销毁

方法一:

  1. void LTDestory(LTNode** pphead)
  2. {
  3. assert(pphead);
  4. assert(*pphead);
  5. //释放头节点以外的节点
  6. LTNode* pcur = (*pphead)->next;
  7. while(pcur != *pphead)
  8. {
  9. LTNode* next = pcur->next;
  10. free(pcur);
  11. pcur = next;
  12. }
  13. //释放头节点
  14. free(*pphead);
  15. *pphead = NULL;
  16. }

方法二:

  1. void LTDestory(LTNode* phead)
  2. {
  3. assert(phead);
  4. //释放头节点以外的节点
  5. LTNode* pcur = phead->next;
  6. while(pcur != phead)
  7. {
  8. LTNode* next = pcur->next;
  9. free(pcur);
  10. pcur = next;
  11. }
  12. //释放头节点
  13. free(phead);
  14. phead = NULL;
  15. }
  16. //由于传入的是值而非地址,因此在函数调用完成后,phead并未为空,需要后续手动置为空
  17. int main()
  18. {
  19. ...
  20. phead = NULL;
  21. ...
  22. }

三.双向链表的尾插

  1. void LTOPushBack(LTNode* phead,SLDataType x)//因为头节点不能修改,因此只需要传入一级指针
  2. {
  3. //头节点不为空
  4. assert(phead);
  5. LTNode* phead = LTBuyNode(x);
  6. //修改新节点指向
  7. newnode->next = phead;
  8. newnode->prev = phead->prev;
  9. //修改尾节点指向
  10. phead->prev->next = newnode;
  11. //修改头节点指向
  12. phead->prev = newnode;
  13. }

四.双向链表的头插

  1. void LTOPushFront(LTNode* phead,SLDataType x)
  2. {
  3. assert(phead);
  4. LTNode* phead = LTBuyNode(x);
  5. newnode->next = phead->next;
  6. newnode->prev = phead;
  7. phead->next->prev = newnode;
  8. phead->next = newnode;
  9. }

五.双向链表的打印

  1. void LTPrint(LTNode* phead,LTDataType x)
  2. {
  3. LTNode* pcur = phead->next;
  4. while(pcur != phead)
  5. {
  6. printf("%d->",pcur->data);
  7. pcur = pcur->next;
  8. }
  9. }

六.双向链表的尾删

  1. void LTPopBack(LTNode* phead)
  2. {
  3. assert(phead);
  4. assert(phead->next != phead);//如果头节点的next和prev指向自己,则当前链表为空
  5. LTNode* del = phead->prev;
  6. LTNode* prev = del->prev;
  7. prev->next = phead;
  8. phead->prev = prev;
  9. free(del);
  10. del = NULL;
  11. }

七.双向链表的头删

  1. void LTPopFront(LTNode* phead)
  2. {
  3. assert(phead);
  4. assert(phead->next != phead);//如果头节点的next和prev指向自己,则当前链表为空
  5. LTNode* del = phead->next;
  6. LTNode* next = del->next;
  7. next->prev = phead;
  8. phead->next = next;
  9. free(del);
  10. del = NULL;
  11. }

八.双向链表的查找

  1. LTNode* LTFind(LTNode* phead,LTDatatype x)
  2. {
  3. assert(phead);
  4. LTNode* pcur = phead->next;
  5. while(pcur != phead)
  6. {
  7. if(pcur->data == x)
  8. {
  9. return pcur;
  10. }
  11. pcur = pcur->next;
  12. }
  13. return NULL;
  14. }

 九.在特定位置之后插入数据

  1. void LTInsert(LTNode* pos,LTDataType x)
  2. {
  3. assert(pos);
  4. LTNode* newnode = LTBuyNode(x);
  5. newnode->next = pos->next;
  6. newnode->prev = pos;
  7. pos->next->prev = newnode;
  8. pos->next = newnode;
  9. }

十.删除特定位置数据

  1. void LTErase(LTNode* pos)
  2. {
  3. assert(pos);
  4. pos->next->prev = pos->prev;
  5. pos->prev->next = pos->next;
  6. free(pos);
  7. pos = NULL;
  8. }

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

闽ICP备14008679号