链表的一些规律总结
链表是灵活运用指针的一个重要的工具,在初学链表的时候,经常会有所遗落而使得形成的链表无法正常运作,在此写下对本人启发很大的几个模板并且总结一些自己经常出问题的注意事项
一、这是一个合并两个升序的链表为另一升序链表的实现在制作的过程中,我考虑的方法是——见缝插针:这类合并就是在思考过程中就是将类似于从针盒中取出找缝,故要固定一个数(针)并移动另一链表(缝)来进行合并
#include <stdio.h> #include <stdlib.h> struct ListNode { int data; struct ListNode *next; }; struct ListNode *createlist(); /*裁判实现,细节不表*/ struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2); void printlist( struct ListNode *head ) { struct ListNode *p = head; while (p) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { struct ListNode *list1, *list2; list1 = createlist(); list2 = createlist(); list1 = mergelists(list1, list2); printlist(list1); return 0; } /* 你的代码将被嵌在这里 */ /* 你的代码将被嵌在这里 */ struct ListNode* mergelists(struct ListNode* list1, struct ListNode* list2) { struct ListNode* head=list1, *c1=list1, * current=NULL,*c2=list2,*pre=head; while (c2) { if (c1 == head && c2->data <= c1->data) { current = c2; c2 = c2->next;//更新针 current->next = c1; head = current; continue; } else if (c1->next) { if (c2->data > c1->data&& c2->data <= c1->next->data) { current = c2; c2 = c2->next; current->next = c1->next; c1->next = current; continue; } } if (c2->data >= c1->data&&c1->next==NULL) { current = c2; c2 = c2->next; c1->next =current; current->next = NULL; continue; } else { c1 = c1->next; } } return head; }
在拆解的过程中,有如下要注意的:
1.注意现在的位置是不是链表头,如果是(要对tail和head的位置进行修改)
2.在链表中间的元素要注意,pre->next,是否可用,否则会引起储存位置的数据混乱——在链表的制作,遍历中都要尤其关注指针会不会指向NULL
3.注意现在的位置是不是链表尾,如果是(要让连接后的next指向NULL)
4.在链表的双重循环过程中,经常会出现if语句,条件的更新也可能放在if语句中,要注意如果没有进入if语句是否要更新
二、围圈踢人问题
问题描述:
#include<stdio.h> #include<stdlib.h> struct NodeList { int data; struct NodeList* next; }; //typedef struct NodeList NodeList; struct List { struct NodeList* head; struct NodeList* tail; }; //typedef struct List List; struct List* createlist(int number); void remove3(struct List* L); int main() { int number; scanf("%d", &number); remove3(createlist(number)); return 0; } struct List* createlist(int number) { struct List* L=(struct List*)malloc(sizeof(struct List)); L->head = NULL; L->head = NULL; struct NodeList* current = NULL; for (int i = 1; i <= number; i++) { current = (struct NodeList*)malloc(sizeof(struct NodeList)); current->data = i; current->next = NULL; if (L->head == NULL) { L->head = current; L->tail = current; } else { L->tail->next = current; L->tail = L->tail->next; } L->tail->next = NULL; current = NULL; } L->tail->next = L->head; return L; } void remove3(struct List* L) { int cnt = 2; struct NodeList* current = L->head->next; struct NodeList* pre = L->head, * kill = NULL; pre = L->head; while (current->next!=current) { if (cnt == 3) { pre->next = current->next; kill = current; current = current->next; kill->next = NULL; cnt = 0; } else { pre = current; current = current->next; } cnt++; } printf("%d", current->data); }
这个问题是remove链表的变形,我从结果出发,即使有2个人也会有人出局,说明最后只剩下一个人,一个人的情况下,围成一个圈,那就是next指向自己,这是while的判断条件。
用for循环与i来填入条件(类似与数组)用另一计数器来计报数情况。
制作中出现的问题:更新更新更新条件(包括tail和current)