在学习链表部分时,推荐背诵本套代码:

1.全部是代码块的形式,所有题目具有相同套路,背诵一个函数可重复使用

2.逻辑清楚,为后续学习打下坚实基础。

3.与学习通课程内容相符合,配合使用更佳

点击蓝色字体快捷食用,如出现错误可联系作者修改

7-1 sdut-C语言实验-顺序建立链表

7-2 sdut-C语言实验-逆序建立链表

7-3 sdut-C语言实验-链表的结点插入

7-4 sdut-C语言实验-单链表中重复元素的删除

7-5 sdut-C语言实验-链表的逆置

7-6 sdut-C语言实验-有序链表的归并

7-7 sdut-C语言实验-单链表的拆分

7-8 sdut-C语言实验-双向链表

7-9 sdut-C语言实验-约瑟夫问题

7-10 sdut-C语言实验-不敢死队问题


7-1 sdut-C语言实验-顺序建立链表

分数 20

作者 马新娟

单位 山东理工大学

输入N个整数,按照输入的顺序建立单链表存储,并遍历所建立的单链表,输出这些数据。

输入格式:

第一行输入整数的个数N;

第二行依次输入每个整数。

输出格式:

输出这组整数。

输入样例:

8

12 56 4 6 55 15 33 62

输出样例:

12 56 4 6 55 15 33 62

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;//指针域,指向下一结点
};//结构体定义结点结构
struct node *creat(int n);//链表建立函数;
void output(struct node *head);//输出函数;
int main(){
    int n;
    scanf("%d",&n);
    struct node *head=creat(n);//引入建立链表函数;
    output(head);//引入输出函数;
    return 0;
}
struct node *creat(int n){//尾插法建立链表函数;
    struct node *head,*tail,*p;//同时定义头尾指针,游动指针;
    head=(struct node *)malloc(sizeof(struct node));//分配空间给头结点;
    head->next=NULL;//头结点置为空;
    tail=head;//尾结点和头结点的指针指向同一结点;
    while(n--){
        p=(struct node *)malloc(sizeof(struct node));//分配空间给结点p;
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;//确定指针域;
    }
    return (head);
}
void output(struct node *head){
    struct node *p=head->next;//注意,容易遗漏!!
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-2 sdut-C语言实验-逆序建立链表

分数 20

作者 马新娟

单位 山东理工大学

输入整数个数N,再输入N个整数,按照这些整数输入的相反顺序建立单链表,并依次遍历输出单链表的数据。

输入格式:

第一行输入整数N;;
第二行依次输入N个整数,逆序建立单链表。

输出格式:

依次输出单链表所存放的数据。

输入样例:

10

11 3 5 27 9 12 43 16 84 22

输出样例:

22 84 16 43 12 9 27 5 3 11

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};//结构体定义结点结构
struct node *creat(int n);//链表建立函数;
void output(struct node *head);//输出函数;
int main(){
    int n;
    scanf("%d",&n);
    struct node *head=creat(n);//引入建立链表函数;
    output(head);//引入输出函数;
    return 0;
}
struct node *creat(int n){//头插法建立链表函数;
    struct node *head,*p;//定义
    head=(struct node *)malloc(sizeof(struct node));//分配空间给头结点;
    head->next=NULL;//头结点置为空;
    while(n--){
        p=(struct node *)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=head->next;//注意,先记上!!!
        head->next=p;//确定指针域;
    }
    return (head);//返回建立好的链表;
}
void output(struct node *head){//链表输出函数;
    struct node *p=head->next;//对p进行赋值(此时p已经分配过空间,不需要再分配);
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-3 sdut-C语言实验-链表的结点插入

分数 20

作者 马新娟

单位 山东理工大学

给出一个只有头指针的链表和 n 次操作,每次操作为在链表的第 m 个元素后面插入一个新元素x。若m 大于链表的元素总数则将x放在链表的最后。

输入格式:

多组输入。每组数据首先输入一个整数n(n∈[1,100]),代表有n次操作。

接下来的n行,每行有两个整数Mi(Mi∈[0,10000]),Xi。

输出格式:

对于每组数据。从前到后输出链表的所有元素,两个元素之间用空格隔开。

输入样例:

4

1 1

1 2

0 3

100 4

输出样例:

3 1 2 4

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
void insert(struct node *p,int key);
void output(struct node *head);
int main(){
    int n,m,x;
    struct node *head,*p;
    while(~scanf("%d",&n))//注意多组输入;
    {//~是按位取反运算符,当scanf函数调用的返回值为0,循环体内的代码将会执行;可以用于循环直到成功获取到输入;
        head=(struct node *)malloc(sizeof(struct node));
        head->next=NULL;//顺序建立链表;
        while(n--){//等同于while(n>0)n--;//这个循环才是真正需要的;
            p=head;//将游动指针p放在头指针位置处进行初始化(有可能插入到头结点之后;
//head作为第一个元素(题目中定义);
            scanf("%d %d",&m,&x);//p此时只是一个游动指针。不是结点,不需要为其申请空间;
            while(m--&&p->next){//while循环的作用:确定题目中给的目标位置;
                p=p->next;
            }
            insert(p,x);
        }
        output(head);
    }
    return 0;
}
void insert(struct node *p,int key){
    struct node *q;
    q=(struct node *)malloc(sizeof(struct node));
    if(!q){//如果非q为真,那么q为0,条件成立;
        printf("不能分配内存空间");
        exit(0);//电脑函数,正常退出;
    }//这个if语句如果去掉更简单;
    q->data=key;
    q->next=NULL;
    q->next=p->next;
    p->next=q;
}
void output(struct node *head){
    struct node *p=head->next;//!!!!!!一一定要有
    while(p!=NULL){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-4 sdut-C语言实验-单链表中重复元素的删除

分数 20

作者 马新娟

单位 山东理工大学

按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个)。

输入格式:

第一行输入元素个数 n (1 <= n <= 15);
第二行输入 n 个整数,保证在 int 范围内。

输出格式:

第一行输出初始链表元素个数;
第二行输出按照逆位序所建立的初始链表;
第三行输出删除重复元素后的单链表元素个数;
第四行输出删除重复元素后的单链表。

输入样例:

10

21 30 14 55 32 63 11 30 55 30

输出样例:

10

30 55 30 11 63 32 55 14 30 21

7

30 55 11 63 32 14 21

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
struct node *creat(int n);//链表建立;
int delete(struct node *head,int n);//重复结点删除;
void output(struct node *head,int n);//链表输出;
int main(){
    struct node *head,*p;//定义;
    int n;
    scanf("%d",&n);//输入n;
    head=creat(n);//建立链表;
    output(head,n);//输出链表;
    n=delete(head,n);//删除结点;//!!!对n进行赋值,一定要有;
    output(head,n);//输出链表;
    return 0;
}
struct node *creat(int n){//链表建立;
    struct node *head,*p;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    for(int i=0;i<n;i++){
        p=(struct node *)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=head->next;
        head->next=p;//逆序建立;
    }
    return (head);
}
int delete(struct node *head,int n){//删除重复结点;
    struct node *p=head;
    while(p->next){
        p=p->next;//每次后移一位;
        struct node *q=p,*qi=q->next;//两个游动指针,qi对比,q辅助;
        while(qi){
            if(p->data==qi->data)//p和qi比较,q作为辅助
            {//注意等号情况:双等号
                q->next=qi->next;
                free(qi);//释放已经删除的结点空间;
                qi=q->next;
                n--;
            }
            else{
                qi=qi->next;
                q=q->next;
            }
        }
    }
    return n;
}
void output(struct node *head,int n){//链表输出函数;
    struct node *p=head->next;
    printf("%d\n",n);
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;//注意不要遗落;
    }
}

7-5 sdut-C语言实验-链表的逆置

分数 20

作者 马新娟

单位 山东理工大学

输入多个整数,以-1作为结束标志,顺序建立一个带头结点的单链表,之后对该单链表的数据进行逆置,并输出逆置后的单链表数据。

输入格式:

输入多个整数,以-1作为结束标志。

输出格式:

输出逆置后的单链表数据。

输入样例:

12 56 4 6 55 15 33 62 -1

输出样例:

62 33 15 55 6 4 56 12

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
struct node *creat(){
    int a;
    struct node *head,*p;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    while(scanf("%d",&a)&&a!=-1){
        p=(struct node *)malloc(sizeof(struct node));
        p->data=a;
        p->next=head->next;
        head->next=p;
    }
    return (head);
}
void output(struct node *head){
    struct node *p=head->next;
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}
int main(){
    struct node *head=creat();
    output(head);
    return 0;
}
#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
struct node *creat();
void reverse(struct node *head);//不需要返回值;
void output(struct node *head);
int main(){
    struct node *head;
    head=creat();
    reverse(head);
    output(head);
    return 0;
}
struct node *creat(){
    struct node *head,*p,*tail;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;
    int a;
    scanf("%d",&a);
    while(a!=-1){
        p=(struct node *)malloc(sizeof(struct node));
        p->data=a;
        tail->next=p;
        tail=p;
        scanf("%d",&a);
    }
    return (head);
}
void reverse(struct node *head){
    struct node *p,*q;
    p=head->next;
    head->next=NULL;
    q=p->next;
    while(p){
        p->next=head->next;
        head->next=p;
        p=q;
        if(q){
            q=q->next;
        }
    }
}
void output(struct node *head){
    struct node *p;
    p=head->next;
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-6 sdut-C语言实验-有序链表的归并

分数 20

作者 马新娟

单位 山东理工大学

分别输入两个有序的整数序列(分别包含M和N个数据),建立两个有序的单链表,将这两个有序单链表合并成为一个大的有序单链表,并依次输出合并后的单链表数据。

输入格式:

第一行输入M与N的值;
第二行依次输入M个有序的整数;
第三行依次输入N个有序的整数。

输出格式:

输出合并后的单链表所包含的M+N个有序的整数。

输入样例:

6 5

1 23 26 45 66 99

14 21 28 50 100

输出样例:

1 14 21 23 26 28 45 50 66 99 100

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
struct node *creat(int n);
struct node *merge(struct node *head1,struct node *head2);
void output(struct node *head);
int main(){
    int m,n;
    scanf("%d %d",&m,&n);
    struct node *head1=creat(m);
    struct node *head2=creat(n);
    head1=merge(head1,head2);
    output(head1);
    return 0;
}
struct node *creat(int n){
    struct node *head,*p,*tail;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;
    while(n--){
        p=(struct node *)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    return (head);
}
struct node *merge(struct node *head1,struct node *head2){
    struct node *tail,*p1,*p2;
    p1=head1->next;
    p2=head2->next;
    tail=head1;
    free(head2);
    while(p1&&p2){
        if(p1->data<p2->data){//由题目中给的数据判断大于小于符号;
            tail->next=p1;
            tail=p1;
            p1=p1->next;
        }
        else{
            tail->next=p2;
            tail=p2;
            p2=p2->next;
        }
    }
    if(p1)
            tail->next=p1;
        else
            tail->next=p2;
    return (head1);
}
void output(struct node *head){
    struct node *p;
    p=head->next;
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-7 sdut-C语言实验-单链表的拆分

分数 20

作者 马新娟

单位 山东理工大学

输入N个整数顺序建立一个单链表,将该单链表拆分成两个子链表,第一个子链表存放了所有的偶数,第二个子链表存放了所有的奇数。两个子链表中数据的相对次序与原链表一致。

输入格式:

第一行输入整数N;;
第二行依次输入N个整数。

输出格式:

第一行分别输出偶数链表与奇数链表的元素个数;
第二行依次输出偶数子链表的所有数据;
第三行依次输出奇数子链表的所有数据。

输入样例:

10

1 3 22 8 15 999 9 44 6 1001

输出样例:

4 6

22 8 44 6

1 3 15 999 9 1001

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *next;
};
struct node *creat(int n);
struct node *split(struct node *head1);
void output(struct node *head);
int main(){
    int n;
    scanf("%d",&n);
    struct node *head1=creat(n);
    struct node *head2=split(head1);
    output(head1);
    output(head2);
    return 0;
}
struct node *creat(int n){
    struct node *head,*p,*tail;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;
    while(n--){
        p=(struct node *)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    return (head);
}
struct node *split(struct node *head1){
    struct node *head2,*tail1,*tail2,*p;
    tail1=head1;
    head2=(struct node *)malloc(sizeof(struct node));
    head2->next=NULL;
    tail2=head2;
    p=head1->next;
    head1->next=NULL;
    int c1=0,c2=0;
    while(p){
        if(p->data%2==0){
            tail1->next=p;
            tail1=p;
            c1++;
        }
        else{
            tail2->next=p;
            tail2=p;
            c2++;
        }
        p=p->next;
    }
    tail1->next=NULL;
    tail2->next=NULL;
    printf("%d %d\n",c1,c2);
    return (head2);
}
void output(struct node *head){
    struct node *p=head->next;
    while(p){
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

7-8 sdut-C语言实验-双向链表

分数 20

作者 马新娟

单位 山东理工大学

学会了单向链表,我们又多了一种解决问题的能力,单链表利用一个指针就能在内存中找到下一个位置,这是一个不会轻易断裂的链。但单链表有一个弱点——不能回指。比如在链表中有两个节点A,B,他们的关系是B是A的后继,A指向了B,便能轻易经A找到B,但从B却不能找到A。一个简单的想法便能轻易解决这个问题——建立双向链表。在双向链表中,A有一个指针指向了节点B,同时,B又有一个指向A的指针。这样不仅能从链表头节点的位置遍历整个链表所有节点,也能从链表尾节点开始遍历所有节点。对于给定的一列数据,按照给定的顺序建立双向链表,按照关键字找到相应节点,输出此节点的前驱节点关键字及后继节点关键字。

输入格式:

第一行两个正整数n(代表节点个数),m(代表要找的关键字的个数)。第二行是n个数(n个数没有重复),利用这n个数建立双向链表。接下来有m个关键字,每个占一行。

输出格式:

对给定的每个关键字,输出此关键字前驱节点关键字和后继节点关键字。如果给定的关键字没有前驱或者后继,则不输出。
注意:每个给定关键字的输出占一行。一行输出的数据之间有一个空格,行首、行末无空格。

输入样例:

10 3

1 2 3 4 5 6 7 8 9 0

3

5

0

输出样例:

在这里给出相应的输出。例如:

2 4

4 6

9

#include<stdio.h>
#include<stdlib.h>
struct node{
    int data;
    struct node *prev;
    struct node *next;
};
struct node *creat(int n);
void search(struct node *head);
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    struct node *head=creat(n);
    while(m--)
        search(head);
    return 0;
}
struct node *creat(int n){
    struct node *head,*tail,*p;
    head=(struct node *)malloc(sizeof(struct node));
    head->prev=NULL;
    head->next=NULL;
    tail=head;
    while(n--){
        p=(struct node *)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=NULL;
        p->prev=tail;//对p进行初始化;
        tail->next=p;
        tail=p;
    }
    return (head);
}
void search(struct node *head){
    int t;
    scanf("%d",&t);
    struct node *p=head->next;
    while(p){
        if(p->data==t){
            struct node *prev=p->prev;
            struct node *next=p->next;
            if(prev!=head)
                printf("%d",prev->data);
            if(next!=NULL){
                if(prev!=head)
                    printf(" %d",next->data);
                else
                    printf("%d",next->data);
            }
            printf("\n");
            // break;
        }
        p=p->next;
    }
}

7-9 sdut-C语言实验-约瑟夫问题

分数 20

作者 马新娟

单位 山东理工大学

n个人想玩残酷的死亡游戏,游戏规则如下:

n个人进行编号,分别从1到n,排成一个圈,顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。

请输出最后一个人的编号。

输入格式:

输入n和m值。

输出格式:

输出胜利者的编号。

输入样例:

5 3

输出样例:

4

#include "stdio.h"//可写成#include<stdio.h>
#include "malloc.h"//可写成#inlcude<stdlib.h>
typedef struct mon{//结构体的定义,typedef为结构体定义一个别名mon;
    int num;
    struct mon *next;
}mon;
mon *creat(int n){// 循环链表的创建函数
    int i;
    mon *p,*tail,*head;
    p=(mon *)malloc(sizeof(mon));
    p->num=1;
    p->next=NULL;   // 第一个结点的生成
    head=p;
    tail=p;
    for(i=2;i<=n;i++){// 顺序建链表,完成其余n-1个结点的插入
        p=(mon *)malloc(sizeof(mon));
        p->num=i;
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    tail->next=head;   // 最后一个结点的指针域指向第一个结点
    return head;
}

int sel(mon *head,int m,int n) // n只猴子报数m出圈的控制函数
{
    int num=0;   // 表示猴子报数的计数变量
    int count=0;  // 用以统计出圈猴子数目的计数变量
    mon *p,*q;   // 分别指向当前结点及其前驱结点的指针
    q=head;//此处不能用q=tail;因为tail未被定义,因此用head;
    while(q->next!=head)
        q=q->next;  // 前驱指针指向尾结点
    //printf("被删除的猴子序号依次是:");
    while(count<n-1){
        p=q->next;
        num++;
        if(num%m==0) { // 找到一个被删结点,完成删除、计数、输出
            q->next=p->next;
            //printf("%3d",p->num);
            free(p);
            count++;
        }
        else
            q=p;
    }
    return q->num;   // 最后一个结点的数据域即为留在圈内猴王的序号
}

int main(){
    int n,m;
    mon *head;
    scanf("%d %d",&n,&m);
    head=creat(n);
    printf("%d\n",sel(head,m,n));
    return 0;
}

7-10 sdut-C语言实验-不敢死队问题

分数 20

作者 马新娟

单位 山东理工大学

说到“敢死队”,大家不要以为我来介绍电影了,因为数据结构里真有这么道程序设计题目,原题如下:

有M个敢死队员要炸掉敌人的一个碉堡,谁都不想去,排长决定用轮回数数的办法来决定哪个战士去执行任务。如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个战士开始计数,当数到5时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第5时,此战士接着去执行任务。以此类推,直到任务完成为止。

这题本来就叫“敢死队”。“谁都不想去”,就这一句我觉得这个问题也只能叫“不敢死队问题”。今天大家就要完成这道不敢死队问题。我们假设排长是1号,按照上面介绍,从1号开始数,数到5的那名战士去执行任务,那么排长是第几个去执行任务的?

输入格式:

输入包括多组数据,每组一行,包含一个整数M(0<=M<=10000)(敢死队人数),若M==0,输入结束,不做处理。

输出格式:

输出一个整数n,代表排长是第n个去执行任务。

输入样例:

9

6

223

0

输出样例:

在这里给出相应的输出。例如:

2

6

132

#include<stdio.h>
#include<stdlib.h>
typedef struct mon{
    int num;
    struct node *next;
}mon;
mon *creat(int n);
int sel(mon *head);
int main(){
    int n;
    mon *head=creat(n);
    while(scanf("%d",&n)&&n!=0){
        head=creat(n);
        printf("%d\n",sel(head));
    }
    return 0;
}
mon *creat(int n){
    mon *head,*tail,*p;
    p=(mon *)malloc(sizeof(mon));
    p->num=1;
    p->next=NULL;
    head=p;
    tail=p;
    for(int i=2;i<=n;i++){
        p=(mon *)malloc(sizeof(mon));
        p->num=i;
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    tail->next=head;
    return (head);
}
int sel(mon *head){
    mon *p,*q;
    int num=0,c=0;
    q=head;
    while(q->next!=head)
        q=q->next;
    while(1){
        p=q->next;
        num++;
        if(num%5==0){
            c++;
            if(p->num==1)
                break;
            q->next=p->next;
            free(p);
        }
        else
            q=p;
    }
    return c;
}

更多推荐