小结 | C 单链表操作 (上)
来源:互联网 发布:双十一淘宝商家多发货 编辑:程序博客网 时间:2024/06/06 08:53
零、声明
typedef int DataType;typedef struct ListNode{ DataType data; struct ListNode* next;}ListNode;
一、从尾到头打印单链表
利用递归的思想,在遇到尾节点之前不返回。
void PrintTailFront(ListNode *list){ if (list == NULL) { return; } PrintTailFront(list->next); printf("%d ", list->data);}
二、删除一个无头单链表的非尾节点
不知道头结点的话,就无法知道需要删除的节点的前一个节点。但是我们知道删除节点的下一个节点,通过将后一个节点的值赋给当前节点的方式,可以实现删除的效果。
void DeleteNoneHeadPos(ListNode *pos){ ListNode *Next == NULL; if (pos == NULL) { printf("Can not find the position\n"); return; } Next = pos->next; pos->data = Next->data; pos->next = Next->next; free(Next);}
三、在无头单链表的一个节点前插入一个节点
跟上一个一样,不知道前一个节点的位置。所以就生成一个新节点,将节点链接到当前节点的后面,再交换两者的值。
void InsertNoneHead(ListNode *pos, DataType x){ ListNode *New = BuyList(x); DataType tmp = 0; if (pos == NULL) { printf("Can not find the position\n"); return; } tmp = New->data; New->data = pos->data; pos->data = tmp; New->next = pos->next; pos->next = New;}
BuyList(DataType x)
//生成新的节点ListNode *BuyList(DataType x){ ListNode *Node = (ListNode *)malloc(sizeof(ListNode)); if (Node == NULL) { printf("Failure to malloc Node\n"); return 0; } Node->data = x; Node->next = NULL; return Node;}
四、单链表实现约瑟夫环
约瑟夫环问题(百度百科),该单链表是头尾相接的环。
DataType JosephRing(ListNode *list, DataType num){ ListNode *Next; DataType tmp = 0; if (list == NULL) { printf("There are not any data\n"); return -1; } //循环结束至只有一个 while (list->next != list) { tmp = num; //一次循环走的次数 while (tmp--) { list = list->next; } //删除节点 Next = list->next; list->data = Next->data; list->next = Next->next; free(Next); } return list->data;}
五、逆置 / 反转单链表
几个特殊的点:
1、为空、只有一个节点,直接返回
2、Next = Next - >next 为NULL 的时候,注意判断 Next = Next - >next -> next 是否为空
3、最后需要将头结点重新赋值,指向新的头节点。
void ReverseList(ListNode **pHead){ ListNode *Next = NULL; ListNode *pre = NULL; if (*pHead == NULL) { printf("The list is empty \n"); return; } if ((*pHead)->next == NULL) { return; } Next = (*pHead)->next; while (*pHead) { (*pHead)->next = pre; pre = (*pHead); (*pHead) = Next; //避免 Next->next->next == NULL访问出错 if (Next != NULL) { Next = Next->next; } } //头结点赋值 *pHead = pre;}
六、单链表排序(冒泡排序)
几个注意的点:
1、需要一个尾指针指向尾部,并每遍历一次就向前回退一个节点
2、用两个指针来移动,并交换
3、一趟结束的标志是尾指针和当前指针地址相同
4、停止的判断条件需要小心
5、可以优化,当有一趟中,并没有交换任何数据,就可以结束排序。
void BubbleSort(ListNode *list){ ListNode *Next = NULL; ListNode *cur = list; ListNode *tail = list; DataType tmp = 0; DataType flag = 0; if (list == NULL || list->next == NULL) { return; } //移动 tail 指向尾部 NULL while (tail) { tail = tail->next; } //判断两指针还未相遇 while (cur != tail) { //将pre指向头结点,cur指向第二个结点 Next = cur->next; //cur->next 在 tail 时候停止 while (cur->next != tail) { if (cur->data > Next->data) { flag = 1; tmp = Next->data; Next->data = cur->data; cur->data = tmp; } cur = Next; Next = Next->next; } if(flag == 0) break; tail = cur; cur = list; }}
七、合并两个有序链表, 合并后依然有序
思路:
1、用一个新的头指针,一个尾指针用来记录尾部的位置
2、比较两个有序链表,小的值赋给新的头结点
3、有了第一个节点之后,利用循环,在尾插的方式下依次按大小插入
4、当其中一个链表为空之后,可以直接将另一个链表剩下的节点直接插入至尾部
ListNode* MergeList(ListNode *L1, ListNode *L2){ ListNode *New = NULL; ListNode *Tail = NULL; //判断是否为空 if (L1 == NULL) { return L2; } if (L2 == NULL) { return L1; } //设置第一个节点 if (L1->data < L2->data) { New = L1; L1 = L1->next; } else { New = L2; L2 = L2->next; } //利用循环对节点向后赋值 Tail = New; while (L1 && L2) { if (L1->data > L2->data) { Tail->next = L2; L2 = L2->next; } else { Tail->next = L1; L1 = L1->next; } Tail = Tail->next; } //如果有还未链接的节点,直接链接到尾指针后面 if (L1) { Tail->next = L1; } if (L2) { Tail->next = L2; } return New;}
八、查找单链表的中间节点,要求只能遍历一次链表
思想:
1、利用快慢指针,慢指针走一步,快指针走两步。
2、如果节点的个数是奇数,循环结束判断条件是 Fast->next == NULL
3、如果节点的个数是偶数,循环结束判断条件是 Fast->next ->next== NULL,同时返回两个中间节点的第一个
ListNode *FindMid(ListNode *list){ ListNode *Slow = list; ListNode *Fast = list; if (list == NULL) { return NULL; } if (list->next == NULL) { return list; } //循环判断,奇数和偶数 while (Fast->next && Fast->next->next) { Slow = Slow->next; Fast = Fast->next->next; } return Slow;}
九、查找单链表的倒数第k个节点,要求只能遍历一次链表
思想:
1、跟上面一样,快指针先走K步,然后快慢指针一起走
2、判断的是,链表中是否有K个节点
ListNode *FindKNode(ListNode *list,DataType k){ ListNode *Slow = list; ListNode *Fast = list; if (list == NULL) { return list; } //判断是否有K个节点,同时Fast指针先走K步 while (k--) { Fast = Fast->next; if (Fast == NULL) { return NULL; } } //快慢指针一起走 while (Fast) { Slow = Slow->next; Fast = Fast->next; } return Slow;}
没了
- 小结 | C 单链表操作 (上)
- C字符串操作小结(1)
- C字符串操作小结(2)
- 文件操作小结(C语言版)
- c++:const 操作小结
- C#----XML操作小结
- c#net操作xml小结
- 【C语言】文件操作小结
- c语言字符串操作小结
- C语言操作符 小结
- 小结 | C语言操作符
- c语言:操作符小结
- C语言操作符小结
- C语言操作符小结
- c++ Prime读书笔记6(c++:const 操作小结)
- 排序小结 (上)
- javaScript小结(上)
- C对文件操作的小结
- 设计模式5-原型模式
- Git使用教程3-提交控制
- 环境变量的配置和myexlipse的破解
- Windows下Maven安装以及配置
- 快速搭建mybatis
- 小结 | C 单链表操作 (上)
- 241 Different Ways to Add Parentheses
- bzoj 3209: 花神的数论题
- react-router-redux 5.0 helloworld
- 获取图片某个像素RGBA值
- 画圆
- 【SpringMVC框架】springmvc的基础知识
- 欢迎使用CSDN-markdown编辑器
- 变量报错