1、移除链表元素
typedef struct ListNode LSNode; struct ListNode* removeElements(struct ListNode* head, int val){ LSNode* newHead,*newTail; //令头结点和尾结点都置为空 newHead = newTail = NULL; //令新指针pcur指向原链表的头结点head,遍历原链表 LSNode* pcur = head; while(pcur) { //当不满足.val==val时,开始向新建的空链表中插入 if(pcur->val != val) { //1、如果新建的链表为空,插入的新节点就是链表的头结点和尾结点 if(newHead == NULL) { newHead = newTail = pcur; } //2、如果新建的链表不为空,直接尾插,让新插进来的结点作为新的尾结点 else { newTail->next = pcur; newTail = newTail->next;//令newTail移位 } } //当满足pcru->val = val,直接跳过进行下一个读取即可 pcur = pcur->next; } //当pcur指向存储整数6的结点时,pcur满足pcur.val = val不会进入if,直接执行pcur = pcur->next,此时pcur = NULL //pcur为NULL,跳出while循环,如果此时直接返回newHead那么新链表的newTail->next指向的位置仍是旧链表存储数据6 //的结点,所以此时需要再判断newTail是否为空,如果不为空则让它最后指向的方向置为空,最后再返回头结点 if(newTail) newTail->next = NULL; return newHead; }
2、翻转链表
typedef struct ListNode LSNode; struct ListNode* reverseList(struct ListNode* head) { //如果传入的链表为空的时候直接返回NULL if(head == NULL) { return NULL; } LSNode* n1,*n2,*n3; n1 = NULL; n2 = head;n3 = head->next; while(n2) { n2->next = n1; n1 = n2; //当n3为空时已经将n3的值交给n2 n2 = n3; //当n3所处的位置不为空时才能接着移动n3,否则结束一次while循环 if(n3) n3 = n3->next; } //此时n1为链表的头 return n1; }
3、合并两个有序链表
typedef struct ListNode LSNode; struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) { //当传入的两个链表其中有一个为空,那么返回另一个链表即可 if(list1 == NULL) { return list2; } if(list2 == NULL) { return list1; } //当两个链表都不为空时,遍历链表 LSNode* cur1 = list1; LSNode* cur2 = list2; //创建新的空链表--带头(结点)单向不循环链表(后续进行尾插等情况就不需要考虑头结点是否为空的情况,减少重复代码) LSNode* newHead,*newTail; //malloc创建一个内存空间,该空间不含有效数据,刚好用于存放该链表的头结点(头结点的有空间但是不存储有效数据) newHead = newTail = (LSNode*)malloc(sizeof(LSNode)); //当两个结点有一个走到空就不能进行比较了 while(cur1 && cur2) { //把值小的结点尾插到新的链表 if(cur1->val < cur2->val) { newTail->next = cur1; newTail = newTail->next; cur1 = cur1->next; } //当cur2->val <= cur1->val时 else { newTail->next = cur2; newTail = newTail->next; cur2 = cur2->next; } } if(cur1) newTail->next = cur1; if(cur2) newTail->next = cur2; return newHead->next; }
4、获取链表的中间结点
typedef struct ListNode LSNode; struct ListNode* middleNode(struct ListNode* head) { if(head == NULL) return NULL; //快慢指针 LSNode* slow,*fast; slow = fast = head; //只要fast和fast->next有一个为空则停止循环 //因为我们也不知道链表的结点数是奇数还是偶数 while(fast && fast->next) //注意二者判断顺序不能交换,因为如果链表结点数为偶数时最后一次循环 //fast指向的位置刚好空,下次循环前判断时,由于fast以及指向空了,更别提fast->next了 //虽然此时slow指向了我们想要的位置但是由于fast->next本身就不合理程序就会报错 //当然如果是奇数个就可以交换 { slow = slow->next; fast = fast->next->next; } //当循环结束时,slow必定指向我们要找的链表中间结点 return slow; }
5、环形链表解决约瑟夫问题
环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)
#include <stdio.h> #include <stdlib.h> typedef struct ListNode ListNode; //申请链表结点函数,同时为结点中添加数据x ListNode* ListByNode(int x) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); if(node == NULL) { perror("malloc fail!"); exit(1); } node->val = x; node->next = NULL; return node; } //创建带环链表 ListNode* CreateList(int n) { ListNode* phead = ListByNode(1); ListNode* pTail = phead; for(int i = 2;i<=n;i++) { ListNode* node = ListByNode(i); pTail->next = node; pTail = pTail->next; } //以上只是在创建单链表,想要让链表成环,需要将尾结点和头结点相连 pTail->next = phead; //这里直接返回尾结点因为有尾结点就能直接找到头结点,返回头结点的话还需要遍历链表才能找到尾结点 return pTail; } //实现函数 int ysf(int n, int m ) { //创建不带头单向循环链表 ListNode* prev = CreateList(n); //进行游戏逻辑实现 ListNode* cur = prev->next;//就是头结点 int count = 1; while (cur->next != cur) { if(count == m) { //删除结点 prev->next = cur->next; free(cur); cur = prev->next; count = 1;//人死后记得让下一个人从1开始报数(count重置为初始值1) } else { //继续向下报数 prev = cur; cur = cur->next; count++; } } //此时链表中只剩下一个结点,返回该结点中的数 return cur->val; }
6、分割链表
面试题 02.04. 分割链表 - 力扣(LeetCode)
typedef struct ListNode ListNode; struct ListNode* partition(struct ListNode* head, int x) { if(head == NULL) return head; //创建带头的大小链表 ListNode* lessHead,*lessTail; ListNode* greatHead,*greatTail; //创建大小链表的哨兵位 lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode)); greatHead = greatTail = (ListNode*)malloc(sizeof(ListNode)); //遍历原链表,将结点放到大小链表中 ListNode* cur = head; //当cur读取原链表后循环结束 while(cur) { //放入小链表 if(cur->val < x) { lessTail->next = cur; lessTail = lessTail->next; } //放入大链表 else { greatTail->next = cur; greatTail = greatTail->next; } cur = cur->next; //cur向后走 } //原链表循环结束此时greatTail后指向的内容并未被置空所以要判断 if(greatTail) greatTail->next = NULL; //小链表的尾和大链表的哨兵位的下一个结点连接起来 lessTail->next = greatHead->next; return lessHead->next; }
~over~