OJ《程序设计基础II》实验2——链表

28 篇文章 2 订阅
17 篇文章 1 订阅

2-1 A - 数据结构实验之链表一:顺序建立链表

#include<stdio.h>
#include<string.h>
typedef struct Node//typedef使用后,下面的结构体可不用struct
{
    int data;
    struct Node *next;
}node;
node *creat(int n)
{
    node *head,*p,*tail;
    head=(node*)malloc(sizeof(node));//malloc函数,建立一个头节点;
    head->next=NULL;//头节点指向空;
    tail=head;//尾节点指向空;
    for(int i=0;i<n;i++)
    {
        p=(node*)malloc(sizeof(node));//建立一个新的节点p;
        scanf("%d",&p->data);//给节点p赋值;
        p->next=NULL;//p指向空;
        tail->next=p;//让tail指向p;
        tail=p;//将p代替tail的位置进行循环,可以实现将新的p顺序加到链表中;
    }//顺序建链表;
    return head;
}
int main()
{
    node *head,*p;
    int n;
    scanf("%d",&n);
    head=creat(n);//顺序建链表;
    p=head->next;//遍历链表;
    while(p)//也可以写while(p!=NULL)
    {
        if(p->next==NULL)
            printf("%d",p->data);
        else printf("%d ",p->data);
        p=p->next;
    }//输出;
    return 0;
}

2-2 B - 数据结构实验之链表二:逆序建立链表

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
node *creat(int n)
{
    node *head,*p;
    head=(node*)malloc(sizeof(node));
    head->next = NULL;//和顺序一样;
    for(int i=0;i<n;i++)
    {
        p=(node*)malloc(sizeof(node));
        scanf("%d",&p->data);
        p->next=head->next;//让p指向head所指的;
        head->next=p;//让head指向p,实现将p逆序建立链表。
    }
    return head;
}
 
int main()
{
    int n;
    scanf("%d",&n);
    node *head,*p;
    head=creat(n);
    p=head->next;
    while(p)
    {
        if(p->next==NULL)
        printf("%d",p->data);
        else printf("%d ",p->data);
        p=p->next;
    }
    return 0;
}
 

2-3 C - 师--链表的结点插入

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
void Insert(node *head,int m,int x)//执行插入操作的函数
{
    node *q=(node *)malloc(sizeof(node)),*p=head;
    q->data=x;//准备好新节点并赋值
    for(int i=0;i<m&&p->next!=NULL;i++)//查找第m个,但如果p->next==NULL也要结束循环
    {
        p=p->next;//建立链表往后走
    }
    q->next=p->next;//将q插入找到的位置
    p->next=q;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        node *head,*p;
        head=(node*)malloc(sizeof(node));
        head->next=NULL;
        for(int i=0; i<n; i++)
        {
            int m,x;
            scanf("%d %d",&m,&x);
            Insert(head,m,x);
        }
        p=head->next;
        while(p)
        {
            if(p->next==NULL)
                printf("%d\n",p->data);
            else
                printf("%d ",p->data);
            p=p->next;
        }
    }
 
    return 0;
}
 

2-4 D - 数据结构实验之链表七:单链表中重复元素的删除

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
 
node *creat(int n)//逆序建表
{
    node *head,*p;
    head=(node*)malloc(sizeof(node));
    head-> next = NULL;
    for(int i=0; i<n; i++)
    {
        p=(node*)malloc(sizeof(node));
        scanf("%d",&p->data);
        p->next=head->next;
        head->next=p;
    }
    return head;
}
void pri(node *p)//输出函数。这个记住,套公式几乎每个题都可以用
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}
 
int main()
{
    int n;
    scanf("%d",&n);
    node *head,*p;
    head=creat(n);
    printf("%d\n",n);
    pri(head->next);
    //下面是删除重复数据
    node *q,*k;//q作为p的跟随结点用于删除操作,k用于遍历前面不重复部分的链表来判断p是否重复
    p=head->next;
    q=head;
    while(p)
    {
        int flag=1;
        k=head->next;
        while(k!=p)
        {
            if(k->data==p->data)
            {
                flag=0;
                n--;
                q->next=p->next;
                p=p->next;
                break;
            }
            k=k->next;
        }
        if(flag==1)
        {
            p=p->next;
            q=q->next;
        }
    }
    printf("%d\n",n);
    pri(head->next);
    return 0;
}
 

2-5 E - 数据结构实验之链表三:链表的逆置

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
node *creat()//顺序建表
{
    int x;//这个x要放在函数里,因为题中未说明输入的数
    node *head,*p,*tail;
    head=(node*)malloc(sizeof(node));
    head-> next = NULL;
    tail=head;
    while(~scanf("%d",&x)&&x!=-1)
    {
        p=(node*)malloc(sizeof(node));
        p->data=x;
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    return head;
}
void pri(node *p)
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}
void Inserve(node *head)//倒置
{
    node *p,*q;
    p=head->next;//p指向head所指向的
    head->next=NULL;//head指向空
    q=p->next;//q为p的下一位
    while(p)
    {
        p->next=head->next;
        head->next=p;//将p放到head的下一位
        p=q;//下一次循环的p到上一次循环的q的位置,也就是说p向后一位
        if(q)
            q=q->next;//q向后一位
    }
}
int main()
{
    node *head;
    head=creat();
    Inserve(head);
    pri(head->next);
    return 0;
}
 

2-6 F - 数据结构实验之链表四:有序链表的归并

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
node *creat(int n)//顺序建链表
{
    node *head,*p,*tail;
    head=(node*)malloc(sizeof(node));
    head-> next = NULL;
    tail=head;
    for(int i=0;i<n;i++)
    {
        p=(node*)malloc(sizeof(node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    return head;
}
void pri(node *p)//输出函数
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}
node *merge(node *head1,node *head2)//归并函数
{
    node *p1,*p2,*tail,*head3;
    p1=head1->next;//遍历链表head1
    p2=head2->next;//遍历链表head2
    head3=(node*)malloc(sizeof(node));//建立新的头节点head3;
    head3->next=NULL;//让head3指向空
    tail=head3;//tail也指向空
    while(p1&&p2)
    {
        if(p1->data<=p2->data)//p1的值小于等于p2
        {
            tail->next=p1;//让tail指向p1
            tail=p1;//让p1取代tail的位置
            p1=p1->next;//p1向后走
        }
        else
        {
            tail->next=p2;
            tail=p2;
            p2=p2->next;
        }//同上
    }//实现从小到大归并排序
    if(p1)
        tail->next=p1;
    else
        tail->next=p2;//排序后,会出现有一条链表多出一个数的情况,此操作可以使多出来的数连接到新联表上;
    return head3;
}
 
int main()
{
    int n,m;
    scanf("%d %d",&m,&n);
    node *head1,*head2,*head3;
    head1=creat(m);
    head2=creat(n);
    head3=merge(head1,head2);
    pri(head3->next);
    return 0;
}
 
 

2-7 G - 数据结构实验之链表五:单链表的拆分

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
    struct Node *next;
}node;
int ji,ou;
node *creat(int n)//这里一定用逆序建链表,用顺序的话,后面可能会出现拆分不彻底情况(没错我之前出现了)
{
    node *head,*p;
    head=(node*)malloc(sizeof(node));
    head-> next = NULL;
    for(int i=0;i<n;i++)
    {
        p=(node*)malloc(sizeof(node));
        scanf("%d",&p->data);
        p->next=head->next;
        head->next=p;
    }
    return head;
}
void pri(node *p)
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}
node *split(node *head1)
{
    node *head2,*p,*q;
    head2=(node*)malloc(sizeof(node));//建立一个新的头节点
    head2->next=NULL;
    p=head1->next;//遍历链表
    q=p->next;
    head1->next=NULL;//让head1指向空
    while(p)
    {
        if(p->data%2==0)//若p值为偶数
        {
            ou++;//偶数个数+1
            p->next=head1->next;
            head1->next=p;//与链表逆置操作相同,逆序链表逆置,得到顺序链表
        }
        else
        {
            ji++;
            p->next=head2->next;
            head2->next=p;
        }//奇数一样操纵
        p=q;
        if(q)
            q=q->next;//逆置操作很常规
    }
    return head2;//返回head2,head2为奇数链表,此时head1也已经变为了偶数链表
}
int main()
{
    int n;
    scanf("%d",&n);
    node *head1,*head2;
    head1=creat(n);
    head2=split(head1);
    printf("%d %d\n",ou,ji);
    pri(head1->next);
    pri(head2->next);
    return 0;
}
 
 

2-8 H - 数据结构实验之链表九:双向链表

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>//动态存储分配函数头文件
typedef struct Node
{
    int data;
    struct Node *next,*front;
}node;
node *creat(int n)
{
    node *head,*p,*tail;
    head=(node*)malloc(sizeof(node));
    head->next = NULL;//head后指向空
    head->front = NULL;//head前也指向空
    tail=head;
    for(int i=0; i<n; i++)
    {
        p=(node*)malloc(sizeof(node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        p->front=tail;//让链表变为双向链表
        tail=p;
    }
    return head;
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    node *head, *p;
    head=creat(n);
    while(m--)//m个关键字,相当于多组输入
    {
        p=head->next;//遍历链表
        int x;
        scanf("%d",&x);
        while(p->data!=x)
            p=p->next;//当p值不是x时,往后走
        if(p->front==head)//如果找到位置的前驱是头节点
            printf("%d\n",p->next->data);//输出后继的值
        else if(p->next==NULL)//如果后继指向空
            printf("%d\n",p->front->data);//输出前驱的值
        else//中间情况
            printf("%d %d\n",p->front->data,p->next->data);
    }
    return 0;
}

2-9 I - 约瑟夫问题

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct Node
{
    int data;
    struct Node *next;
} node;
node *creat(int n)
{
    node *head,*p,*tail;
    p=(node*)malloc(sizeof(node));
    p->data=1;
    p->next=NULL;
    head=tail=p;//循环链表相当于没有真正意义上的头节点和尾节点,所以可以看作三个一样,但是“头节点”也需要赋值,也就是上面的p->data=1;
    for(int i=2; i<=n; i++)
    {
        p=(node*)malloc(sizeof(node));
        p->data=i;//给p赋值
        p->next=NULL;
        tail->next=p;
        tail=p;
    }//相当于是顺序建链表;
    tail->next=head;//循环链表构建完成
    return head;
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    node *head, *p,*q;
    head=creat(n);
    q=head;//也就是说q赋值为1;
    while(q->next!=head)//q不回到那个head的q时
        q=q->next;//q往下走
    int a=0;//用于统计循环链表中向后走及位
    while(q->next!=q)
    {
        p=q->next;
        a++;//向后走的位数
        if(a==m)//如果走到第m位了
        {
            q->next=p->next;//让p取代q
            free(p);//释放p
            a=0;//a回到0,重新开始记数
        }
        else
            q=p;
    }
    printf("%d",q->data);//输出剩下的最后一个q
    return 0;
}

2-10 J - 不敢死队问题

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct Node
{
    int data;
    struct Node *next;
} node;
 
node *creat(int n)//建立循环链表
{
    node *head,*p,*tail;
    p=(node*)malloc(sizeof(node));
    p->data=1;
    p->next=NULL;
    head=tail=p;
    for(int i=2; i<=n; i++)
    {
        p=(node*)malloc(sizeof(node));
        p->data=i;
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    tail->next=head;
    return head;
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n!=0)
    {
        node *head, *p,*q;
        head=creat(n);
        q=head;
        while(q->next!=head)
            q=q->next;
        int a=0,b=0;
        while(q->next!=q)
        {
            p=q->next;
            a++;
            if(a==5)
            {
                if(p->data==1)
                    break;
                q->next=p->next;
                free(p);
                a=0;
                b++;
            }
            else
                q=p;
        }
        printf("%d\n",b+1);
    }
    return 0;
}//与约瑟夫环差不多

加油加油加油!!!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CRAEN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值