leetcode链表题
链表:
- 倒序输出链表
- 链表的倒数第k个节点
- 合并两个排序的链表
倒序输出链表
两种思路:
1.利用栈:遍历链表,将链表元素添加的栈中,遍历结束后,从栈顶依次取出元素即可。
2.利用链表:新建一个新链表,遍历旧链表,将元素插入新链表的头指针后面,遍历结束,遍历新链表即可。
这里利用都是栈先进后出的特性,利用数组+头指针构建栈,需要解决扩容问题,利用链表就没有这个问题,但需要更多的内存空间存储节点指针。
#include <stdio.h> #include<malloc.h> //声明链表节点类型 typedef struct LISTtag LISTtagNode; struct LISTtag{ int value; LISTtagNode *next; }; #define M 8 typedef struct stall Stall; struct stall{ int ele[M]; int top; }; //创建链表 LISTtagNode * create(){ LISTtagNode *head; head = (LISTtagNode*)malloc(sizeof(LISTtagNode)); head->next = NULL; return head; } //在链表尾新增节点 int LinKListInsertbottom(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点为最后一个节点 node->value = value; node->next = NULL; LISTtagNode *t = head; //找到尾指针 while (t->next != NULL) { t = t->next; } t->next= node; return 1; } //在链表尾新增节点 int LinKListInserttop(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点为最后一个节点 node->value = value; node->next = head->next; head->next = node; return 1; } //打印链表 int PrindLinKList(LISTtagNode *head){ if(head == NULL){ return -1; } LISTtagNode *t = head; while (t->next != NULL) { t = t->next; printf("%d ", t->value); } return 1; } //修改某个位置的值 int update(LISTtagNode *head,int index,int value){ if(head == NULL){ return -1; } LISTtagNode *t = head; int i = 0; //要么是最后一个节点,要么超出index while ((t->next != NULL)&&(i<index)) { t = t->next; i++; } //1.t->next ==NULL,退出循环,i<index不满足情况 //2.i>=index,退出循环,t->next != NULL不满足情况 //3.上面两种情况同时发生 //如果为最后一个节点或者超出index才会执行下列语句 if(i == index && i != 0 ){//i != 0,头节点没有存储数据 t->value = value; } return 1; } int PrindLinKListreverse1(LISTtagNode *head,Stall *stall1){ if(head == NULL){ return -1; } LISTtagNode *node = head; while(node->next != NULL){ node = node->next; addone(stall1,node->value); } topall(stall1); return 1; } void addone(Stall *stall1,int value){ if((stall1->top)<M){ stall1->ele[stall1->top] = value; stall1->top ++; } } void topall(Stall *stall1){ stall1->top --; printf("\n栈(数组+头指针)反序打印链表:"); while((stall1->top)>=0){ printf("%d ",stall1->ele[stall1->top]); stall1->top --; } } int PrindLinKListreverse2(LISTtagNode *head){ if(head == NULL){ return -1; } LISTtagNode *node = head; LISTtagNode *newhead = create(); while(node->next != NULL){ node = node->next; LinKListInserttop(newhead,node->value); } printf("\n链表头插法反序打印链表:"); PrindLinKList(newhead); return 1; } int main () { LISTtagNode *head = create(); LinKListInsertbottom(head,7); LinKListInsertbottom(head,22); LinKListInsertbottom(head,3); LinKListInsertbottom(head,43); LinKListInsertbottom(head,32); LinKListInsertbottom(head,42); LinKListInsertbottom(head,12); LinKListInsertbottom(head,14); LinKListInsertbottom(head,14); printf("\n正序打印链表:"); PrindLinKList(head); //利用数组+头指针构建栈,反序链表,先进后出 Stall *stall1; stall1 = (Stall*)malloc(sizeof(Stall)); stall1->top = 0; PrindLinKListreverse1(head,stall1); //利用链表头插法,新建一个链表,在头部插入解决另一个链表的反序输出 PrindLinKListreverse2(head); return 0; }
链表的倒数第k个节点
思路:
我们可以定义两个指针。第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;从第k步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第k个结点。
效果示意图,以链表总共6个结点,求倒数第3个结点为例:
#include <stdio.h> #include<malloc.h> //声明链表节点类型 typedef struct LISTtag LISTtagNode; struct LISTtag{ int value; LISTtagNode *next; }; //创建链表 LISTtagNode * create(){ LISTtagNode *head; head = (LISTtagNode*)malloc(sizeof(LISTtagNode)); head->next = NULL; return head; } //在链表尾新增节点 int LinKListInsertbottom(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点为最后一个节点 node->value = value; node->next = NULL; LISTtagNode *t = head; //找到尾指针 while (t->next != NULL) { t = t->next; } t->next= node; return 1; } //在链表头新增节点 int LinKListInserttop(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点跟在头节点后 node->value = value; node->next = head->next; head->next = node; return 1; } //打印链表 int PrindLinKList(LISTtagNode *head){ if(head == NULL){ return -1; } LISTtagNode *t = head; while (t->next != NULL) { t = t->next; printf("%d ", t->value); } return 1; } //修改某个位置的值 int update(LISTtagNode *head,int index,int value){ if(head == NULL){ return -1; } LISTtagNode *t = head; int i = 0; //要么是最后一个节点,要么超出index while ((t->next != NULL)&&(i<index)) { t = t->next; i++; } //1.t->next ==NULL,退出循环,i<index不满足情况 //2.i>=index,退出循环,t->next != NULL不满足情况 //3.上面两种情况同时发生 //如果为最后一个节点或者超出index才会执行下列语句 if(i == index && i != 0 ){//i != 0,头节点没有存储数据 t->value = value; } return 1; } LISTtagNode * printindex(LISTtagNode *head,int index){ int i = 0; LISTtagNode *t1 = head; while((t1->next!=NULL)&&(i<index)){ t1 = t1->next; i++; } if(i==index){ LISTtagNode *t2 = head; while((t1->next!=NULL)){ t1 = t1->next; t2 = t2->next; } printf("\n%d ",t2->value); return t2; } return NULL; } int main () { LISTtagNode *head = create(); LinKListInsertbottom(head,7); LinKListInserttop(head,22); LinKListInsertbottom(head,3); LinKListInsertbottom(head,43); LinKListInsertbottom(head,32); LinKListInsertbottom(head,42); LinKListInsertbottom(head,12); LinKListInsertbottom(head,14); LinKListInsertbottom(head,14); printf("\n正序打印链表:"); PrindLinKList(head); printindex(head,3); return 0; }
合并两个排序的链表
思路:
合并两个递增的链表。
需要新建一个新链表,因为两个旧链表已经完成排序,我们需要比较两个旧链表的元素,每次选取比较中更小的元素插入新链表,这里需要移动指针,已经插入的需要往后移,没有插入的不动即可,最后可能有一个旧链表多出来一些元素,将这个旧链表剩下的元素插入新链表中即可。
#include <stdio.h> #include<malloc.h> //声明链表节点类型 typedef struct LISTtag LISTtagNode; struct LISTtag{ int value; LISTtagNode *next; }; //创建链表 LISTtagNode * create(){ LISTtagNode *head; head = (LISTtagNode*)malloc(sizeof(LISTtagNode)); head->next = NULL; return head; } //在链表尾新增节点 int LinKListInsertbottom(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点为最后一个节点 node->value = value; node->next = NULL; LISTtagNode *t = head; //找到尾指针 while (t->next != NULL) { t = t->next; } t->next= node; return 1; } //在链表头新增节点 int LinKListInserttop(LISTtagNode *head,int value){ if(head == NULL){ return -1; } //新建节点 LISTtagNode *node; node = (LISTtagNode*)malloc(sizeof(LISTtagNode)); //节点赋值,此节点跟在头节点后 node->value = value; node->next = head->next; head->next = node; return 1; } //打印链表 int PrindLinKList(LISTtagNode *head){ if(head == NULL){ return -1; } LISTtagNode *t = head; while (t->next != NULL) { t = t->next; printf("%d ", t->value); } return 1; } //修改某个位置的值 int update(LISTtagNode *head,int index,int value){ if(head == NULL){ return -1; } LISTtagNode *t = head; int i = 0; //要么是最后一个节点,要么超出index while ((t->next != NULL)&&(i<index)) { t = t->next; i++; } //1.t->next ==NULL,退出循环,i<index不满足情况 //2.i>=index,退出循环,t->next != NULL不满足情况 //3.上面两种情况同时发生 //如果为最后一个节点或者超出index才会执行下列语句 if(i == index && i != 0 ){//i != 0,头节点没有存储数据 t->value = value; } return 1; } //修改某个位置的值 int sort(LISTtagNode *head1,LISTtagNode *head2){ if(head1 == NULL|| head2 == NULL ){ return -1; } LISTtagNode *newhead = create(); LISTtagNode *t1 = head1->next; LISTtagNode *t2 = head2->next; //如果两个链表其中有一个链表的节点为NULL,则退出循环 while((t1!= NULL)&&(t2!= NULL)){ if(t1->value<=t2->value){ LinKListInsertbottom(newhead,t1->value); t1 = t1->next; }else{ LinKListInsertbottom(newhead,t2->value); t2 = t2->next; } } if(t1 == NULL){ while(t2 !=NULL){ LinKListInsertbottom(newhead,t2->value); t2 = t2->next; } }else{ while(t1 !=NULL){ LinKListInsertbottom(newhead,t1->value); t1 = t1->next; } } printf("\n合并打印链表:"); PrindLinKList(newhead); return 1; } int main () { LISTtagNode *head1 = create(); LISTtagNode *head2 = create(); LinKListInsertbottom(head1,7); LinKListInserttop(head1,9); LinKListInsertbottom(head1,23); LinKListInsertbottom(head1,43); LinKListInsertbottom(head1,45); LinKListInsertbottom(head1,65); printf("\n正序打印链表:"); PrindLinKList(head1); LinKListInsertbottom(head2,2); LinKListInserttop(head2,3); LinKListInsertbottom(head2,4); LinKListInsertbottom(head2,9); LinKListInsertbottom(head2,32); LinKListInsertbottom(head2,34); printf("\n正序打印链表:"); PrindLinKList(head2); sort(head1,head2); return 0; }