赞
踩
注意: 哨兵位创建后,首尾连接自己
- // 创建节点
- ListNode* ListBuyNode(ListDatatype x)
- {
- ListNode* node = (ListNode*)malloc(sizeof(ListNode));
- if (node == NULL)
- {
- perror("malloc err!");
- exit(1);
- }
-
- node->data = x;
- node->next = node->prev = node; //哨兵位创建后,首尾连接自己
-
- return node;
- }
-
- // 双向链表的初始化
- void ListInit(ListNode** pphead)
- {
- // 给双链表创建一个哨兵位
- *pphead = ListBuyNode(-1);
- }
相当于给头节点也就是哨兵位附上一个无效值,我们在后续的操作中不可以访问哨兵位,它的作用只是一个向导。
- // 双向链表的打印
- void ListPrint(ListNode* phead)
- {
- // 遍历链表
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- // 打印
- printf("%d->", pcur->data);
- pcur = pcur->next;
- }
- printf("\n");
- }
每次打印需要检查所传的值避开头节点, 我们第一个打印的值要从头节点的下一个节点开始,知道遍历链表走到头节点结束。
- // 双向链表的尾插
- void ListPushBack(ListNode* phead, ListDatatype x)
- {
- // 创建一个存放数据的新节点
- ListNode* newnode = ListBuyNode(x);
-
- // 进行尾插
- // 新节点连接
- newnode->prev = phead->prev;
- newnode->next = phead;
-
- // 改变原来链表的连接
- phead->prev->next = newnode;
- phead->prev = newnode;
- }
尾插我们需要注意的是先要创建一个新的节点储存我要插入的值,在链表连接的时候首先把新创建节点的首尾相连,这样可以避免因为改动了原链表的指向而导致的问题!
如:我们先用(phead->prev)节点的*next指向了新节点(newnode), 那么原本d3(phead->prev)的指向就会被覆盖,后续难以找到。
- void ListPushFront(ListNode* phead, ListDatatype x)
- {
- // 创建一个存放数据的新节点
- ListNode* newnode = ListBuyNode(x);
-
- // 进行头插
- // 新节点连接
- newnode->prev = phead;
- newnode->next = phead->next;
-
- // 改变原来链表的连接
- phead->next->prev = newnode;
- phead->next = newnode;
- }
和尾插的操作差不多,要注意先新后原——先连接新链表,后更改原来的链表。
- void ListPopBack(ListNode* phead)
- {
- assert(phead && phead->next != phead);
-
- // 进行尾删除
- ListNode* del = phead->prev;// 这边创建del方便理解,不然指向过多太乱
- del->prev->next = del->next;
- del->next->prev = del->prev;
-
- // 释放空间
- free(del);
- del = NULL;
- }
- void ListPopFront(ListNode* phead)
- {
- assert(phead && phead->next != phead);
-
- // 进行头删除
- ListNode* del = phead->next;// 这边创建del方便理解,不然指向过多太乱
- del->next->prev = phead;
- phead->next = del->next;
-
- // 释放空间
- free(del);
- del = NULL;
- }
- ListNode* ListFind(ListNode* phead, ListDatatype x)
- {
- // 遍历双向链表
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- // 打印
- if (pcur->data == x)
- {
- return pcur;//如果找到返回节点
- }
- pcur = pcur->next;
- }
-
- // 没有找到
- return NULL;
- }
- void ListInsret(ListNode* pos, ListDatatype x)
- {
- assert(pos);
-
- // 创建一个存放数据的新节点
- ListNode* newnode = ListBuyNode(x);
-
- // 插入
- // 新节点连接
- newnode->prev = pos;
- newnode->next = pos->next;
-
- // 原链表连接
- pos->next->prev = newnode;
- pos->next = newnode;
- }
- void ListErase(ListNode* pos)
- {
- //pos理论上来说不能为phead,但是没有参数phead,无法增加校验
- assert(pos);
-
- pos->prev->next = pos->next;
- pos->next->prev = pos->prev;
-
- free(pos);
- pos = NULL;
- }
- void ListDesTroy(ListNode* phead)
- {
- assert(phead);
-
- // 遍历删除
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- ListNode* next = pcur->next;
- free(pcur);
- pcur = next;
- }
- //此时pcur指向phead,而phead还没有被销毁
- free(phead);
- phead = NULL;
- printf("销毁成功!");
- }
销毁链表需要从头一个一个往下删除释放空间,我们创建pcur指针指向头节点,而next指针指向下一个节点,next指针的作用是防止我们删除当前节点时找不到下一个节点了。循环遍历删除,直到最后删除头节点(哨兵位)。
测试文件:用于检验代码执行的有效性
- #include "List.h"
-
- void ListNodetext()
- {
- ListNode* plist;
- ListInit(&plist);
-
- // 测试尾插
- ListPushBack(plist, 1);
- /*ListPrint(plist);*/
- ListPushBack(plist, 2);
- /*ListPrint(plist);*/
- ListPushBack(plist, 3);
- ListPrint(plist); // 1->2->3->
-
- // 测试头插
- //ListPushFront(plist, 6);
- //ListPrint(plist);
- //ListPushFront(plist, 7);
- //ListPrint(plist);
- //ListPushFront(plist, 8);
- //ListPrint(plist);
-
- // 测试尾删
- //ListPopBack(plist);
- //ListPrint(plist);
- //ListPopBack(plist);
- //ListPrint(plist);
- //ListPopBack(plist);
- //ListPrint(plist);
-
- // 测试头删
- //ListPopFront(plist);
- //ListPrint(plist);
- //ListPopFront(plist);
- //ListPrint(plist);
- //ListPopFront(plist);
- //ListPrint(plist);
-
- // 测试查找
- //ListNode* find = ListFind(plist, 30);
- //if (find == NULL)
- //{
- // printf("没有找到!");
- //}
- //else
- //{
- // printf("找到了!");
- //}
-
- // 测试pos位置之后插入
- //ListNode* find = ListFind(plist, 2);
- //ListInsret(find, 5);
- //ListPrint(plist);
-
- // 测试删除pos节点
- //ListNode* find = ListFind(plist, 3);
- //ListErase(find);
- //find = NULL;
- //ListPrint(plist);
-
- ListDesTroy(plist);
- plist = NULL;
- }
-
- int main()
- {
- ListNodetext();
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。