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("
栈(数组+头指针)反序打印链表:");
    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("
链表头插法反序打印链表:");
    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("
正序打印链表:");
    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("
%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("
正序打印链表:");
    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("
合并打印链表:");
    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("
正序打印链表:");
    PrindLinKList(head1);
    
    LinKListInsertbottom(head2,2);
    LinKListInserttop(head2,3);
    LinKListInsertbottom(head2,4);
    LinKListInsertbottom(head2,9);
    LinKListInsertbottom(head2,32);
    LinKListInsertbottom(head2,34);
    printf("
正序打印链表:");
    PrindLinKList(head2);
    sort(head1,head2);
    return 0;
}
原文地址:https://www.cnblogs.com/-wenli/p/12518170.html