山理工-PTA-数据结构与算法-实验二-参考代码(简单易懂)

顺序打乱,分类差不多是同一个类型的哦

链表的一些应用

7-6 链表去重

#include <stdio.h>
#include <stdlib.h>
#include<math.h> 

struct node//利用结构体
{
    int data,next;//存储 键值,下一个结点的地址
}a[100005];//下标 表示 地址

int main()
{
    int f[100005]={0};//置所有键值状态为0
    int ne[100005];//表示 去重后的链表 存储地址
    int de[100005];//表示 删除后的链表 存储地址
    int first_add,n,//输入 首地址和个数
    int i;
    int l1=0;//表示 ne[]数组中的个数
    int l2=0;//de[]数组中的个数
    int add,data,next;//定义 地址,键值,下一个结点的地址
    
    //输入
    scanf("%d %d",&first_add,&n);
    for(i=0;i<n;i++)
    {
        scanf("%d %d %d",&add,&data,&next);
        a[add].data=data;
        a[add].next=next;
    }
    //从第一个地址开始,判断是否为空地址
    add=first_add;//从首地址开始
    while(add!=-1)
    {
        int data=abs(a[add].data);//键值 取绝对值
        if(f[data]==0)//第一次出现,存储到ne数组
        {
            ne[l1++]=add;
            f[data]=1;//置此时状态为1
        }
        else
            de[l2++]=add;//否则存储到de数组
        add=a[add].next;//依次到下一个地址
    }
    
    //输出
    //输出 去重后的
    //注意 下一个地址的输出 不是原来链表的下一个,而是新的链表的下一个
    for(i=0;i<l1;i++)
    {
        if(i==l1-1)
            printf("%05d %d -1\n",ne[i],a[ne[i]].data);//地址,键值
        else
            printf("%05d %d %05d\n",ne[i],a[ne[i]].data,ne[i+1]);//地址,键值,下一个地址
    }
    //输出 删除的
    for(i=0;i<l2;i++)
    {
        if(i==l2-1)
            printf("%05d %d -1\n",de[i],a[de[i]].data);
        else
            printf("%05d %d %05d\n",de[i],a[de[i]].data,de[i+1]);
    }
    return 0;
}


7-3 重排链表

include <stdio.h>
#include <stdlib.h>
struct node//利用结构体
{
    int data,next;//存储 键值,下一个节点的地址
}a[100005];// 下标 表示 地址

int main()
{
    int first_add,n,add,data,next;//第一个地址,n个数据,定义地址,键值,下一个节点的地址
    //输入
    scanf("%d %d",&first_add,&n);
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%d %d %d",&add,&data,&next);
        a[add].data=data;
        a[add].next=next;
    }
    
    
    int in[100005];//in数组表示 原来的链表 存储地址
    int ne[100005];//ne数组表示 重排的链表 存储地址
    int count=0;//in数组中的个数
    
    //从第一个地址开始,判断地址是否为空
    add=first_add;//从首地址开始
    while(add!=-1)
    {
        in[count++]=add;//存储地址
        add=a[add].next;
    }
    
    //重排链表,将原链表的最后一个(倒数第二),移到第一个(第二个)
    //          将原链表的第一个(第二个),移到最后一个(倒数第二)
    int in_left=0,in_right=count-1;//分别指向in数组的最左侧和最右侧
    int ne_point=0;//指向ne数组
    
    while(in_left<=in_right)
    {
        if(in_left<in_right)
        {
            ne[ne_point]=in[in_right];//将原链表的最后一个,移到第一个
            ne_point++;
            in_right--;

            ne[ne_point]=in[in_left];//将原链表的第一个,移到最后一个
            ne_point++;
            in_left++;
        }
        else
        {
            ne[ne_point]=in[in_left];
            ne_point++;
            in_left++;

        }
    }
    
    //输出
    //依旧注意下一个地址的输出
    for(i=0;i<count;i++)
    {
        if(i==count-1)
            printf("%05d %d -1\n",ne[i],a[ne[i]].data);
        else
            printf("%05d %d %05d\n",ne[i],a[ne[i]].data,ne[i+1]);
    }
    return 0;
}

两个链表

7-1 两个有序链表序列的合并

#include <stdio.h>
#include <stdlib.h>
//结构体
struct node
{
    int data;
    struct node*next;
};

int count=0;//定义 链表的长度

//利用头指针,创建链表
struct node* creat()
{
    struct node*head,*tail,*p;//定义指针
    //创建头指针
    head=(struct node*)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;//尾指针
    //输入,创建链表
    int x;
    while(~scanf("%d",&x)&&x!=-1)
    {
        p=(struct node*)malloc(sizeof(struct node));
        p->data=x;
        
        tail->next=p;
        tail=p;
        
        count++;
    }
    return head;
};

//输出链表
void show(struct node*p)
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}

//合并两个链表
struct node* he(struct node*head1,struct node*head2)
{
    struct node*p1,*p2,*tail,*head3;
    p1=head1->next;
    p2=head2->next;
    //创建新的头指针,来建立新的链表
    head3=(struct node*)malloc(sizeof(struct node));
    head3->next=NULL;
    tail=head3;
    
    while(p1&&p2)
    {
        if(p1->data<p2->data)//p1的值小,就先将p1的值放在新的链表中
        {
            tail->next=p1;
            tail=p1;
            p1=p1->next;
        }
        else//p2的值小,就将p2的值放在新的链表中
        {
            tail->next=p2;
            tail=p2;
            p2=p2->next;
        }
        //将剩余的值 放在新的链表后面
        if(p1)
            tail->next=p1;
        else
            tail->next=p2;
    }
    return head3;
};
int main()
{
    
    struct node*head1,*head2,*head3;
    //输入
    head1=creat();
    head2=creat();
    //根据链表的的长度,输出
    if(count)
    {
        head3=he(head1,head2);
        show(head3->next);
    }
    else
        printf("NULL\n");
    return 0;
}

7-2 两个有序链表序列的交集

#include <stdio.h>
#include <stdlib.h>
//结构体
struct node
{
    int data;
    struct node*next;
};

int f=0;//置状态为0,来判断是否有交集
//创建链表
struct node*creat()
{
    struct node*head,*tail,*p;
    //创建头指针
    head=(struct node*)malloc(sizeof(struct node));
    head->next=NULL;
    //尾指针
    tail=head;
    //输入,创建链表
    int x;
    while(~scanf("%d",&x)&&x!=-1)
    {
        p=(struct node*)malloc(sizeof(struct node));
        p->data=x;
        
        tail->next=p;
        tail=p;
    }
    return head;
};
//输出链表
void show(struct node*p)
{
    while(p)
    {
        if(p->next==NULL)
            printf("%d\n",p->data);
        else
            printf("%d ",p->data);
        p=p->next;
    }
}
//两个链表的交集
struct node*bing(struct node*head1,struct node*head2)
{
    struct node*p1,*p2,*head3,*tail;
    p1=head1->next;
    p2=head2->next;
    //创建新的链表,新的头指针
    head3=(struct node*)malloc(sizeof(struct node));
    head3->next=NULL;
    tail=head3;
    while(p1&&p2)
    {
        if(p1->data<p2->data)//p1的值小,p1指针后移
        {
            p1=p1->next;
        }
        else if(p1->data>p2->data)//p2的值小,p2指针后移
        {
            p2=p2->next;
        }
        else if(p1->data==p2->data)//直到p1=p2,将该值放到新的链表中,p1,p2一起后移
        {
            f=1;//状态置为1
            tail->next=p1;//该值放在新的链表中
            tail=p1;
            //指针后移
            p1=p1->next;
            p2=p2->next;
        }
    }
    return head3;
};

int main()
{
    //输入
    struct node*head1,*head2,*head3;
    head1=creat();
    head2=creat();
    
    head3=bing(head1,head2);
    //判断是否有交集
    if(f==0)
        printf("NULL");
    else
        show(head3->next);
        
    return 0;
}

单向链表的一些基础操作

7-5 单链表的创建及遍历

#include <stdio.h>
#include <stdlib.h>
//结构体
struct node
{
    int data;
    struct node* next;
};
//创建链表
struct node* creat(int n)
{
    struct node*head,*tail,*p;
    //创建头指针
    head=(struct node*)malloc(sizeof(struct node));
    head->next=NULL;
    //尾指针
    tail=head;
    //读入n值,创建链表
    int i;
    for(i=0;i<n;i++)
    {
        p=(struct node*)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=NULL;
        
        tail->next=p;
        tail=p;
    }
    return head;
};
//输出链表
void show(struct 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);
    struct node*head;
    //输入
    head=creat(n);
    show(head->next);
    return 0;
}

7-7 单链表就地逆置

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
//结构体
typedef struct node
{
    int data;
    struct node*next;
}node;//将 struct node 命名为 node
//创建链表
node*creat()
{
    node*head,*p;
    //创建头指针
    head=(node*)malloc(sizeof(node));
    head->next=NULL;
    //输入,创建链表
    int x;
    while(~scanf("%d",&x)&&x!=-1)
    {
        p=(node*)malloc(sizeof(node));
        p->data=x;
        p->next=NULL;
        
        p->next=head->next;
        head->next=p;

    }
    return head;
}
//输出链表
void show(node*p)
{
    while(p)
    {
        if(p->next)
            printf("%d ",p->data);
        else
            printf("%d\n",p->data);
        p=p->next;
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    //多组测试数据
    while(t--)
    {
        node*head;
        head=creat();
        show(head->next);
    }
    return 0;
}

7-9 头插法创建单链表、遍历链表、删除链表

注意:对每组测试数据,创建链表,遍历链表输出之后,一定要删除链表,否则会出现“内存超限”。

所以在这里,参考代码,我使用数组简单些

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int main()
{
    //输出测试数据
    int t;
    scanf("%d",&t);
    
    while(t--)
    {
        int a[1000005];//数组存储
        int i=0;//表示数组长度
        int x;//表示输入数据
        //数组存储 输入数据
        while(~scanf("%d",&x)&&x!=-1)
        {
            a[i]=x;
            i++;
        }
        //逆向输出
        int j;
        for(j=i-1;j>=0;j--)
        {
            if(j==0)
                printf("%d \n",a[j]);
            else
                printf("%d ",a[j]);
        }
    }

    return 0;
}

循环链表和双向链表的操作

7-4 约瑟夫环

#include <stdio.h>
#include <stdlib.h>
//结构体
struct node
{
    int data;
    struct node*next;
};
//创建链表
struct node*creat(int n)
{
    struct node*head,*tail,*p;
    //输入第一个数
    p=(struct node*)malloc(sizeof(struct node));
    p->data=1;
    //头尾指针
    head=tail=p;
    //输入其他的数,创建链表
    int i;
    for(i=2;i<=n;i++)
    {
        p=(struct node*)malloc(sizeof(struct node));
        p->data=i;
        
        tail->next=p;
        tail=p;
    }
    //创建 循环链表
    tail->next=head;
    return head;
};
//输出链表
void show(struct 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,m;
    scanf("%d %d",&n,&m);
    
    struct node*head,*p,*q;
    head=creat(n);
    //从头指针开始,
    q=head;
    while(q->next!=head)
        q=q->next;
        
    int a=0;//a为计数器
    //从头指针开始,报数
    while(q->next!=q)
    {
        p=q->next;
        a++;
        if(a==m)//报数到m
        {
            printf("%d ",p->data);//输出序号
            
            q->next=p->next;//将p删除释放
            free(p);
            
            a=0;//计数器归零
        }
        else//指针后移
            q=p;
    }
    //输出最后的序号
    printf("%d",q->data);
    return 0;
}

7-8 带头节点的双向循环链表操作

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
//结构体
typedef struct node
{
    int data;
    struct node*next;
    struct node*front;
}node;

int main()
{
    node*head,*p,*q,*h;
    //头指针创建
    head=(node*)malloc(sizeof(node));
    head->next=NULL;//头节点的后继
    head->front=NULL;//头节点的前驱
    head->data=1;//输入第一个值
    
    q=head;
    h=head;
    //输入其他的值,创建链表
    int x;
    int count=1;
    while(~scanf("%d",&x)&&x!=-1)
    {
        count++;
        p=(node*)malloc(sizeof(node));
        p->data=x;
        p->next=NULL;
        p->front=NULL;
        
        if(count%2!=0)//是奇数个,前移
        {
            q->front=p;//头结点前驱 指向 p
            p->next=q;//p的后继 指向 头节点
            q=p;//头指针前移
        }
        else//是偶数个,后移
        {
            h->next=p;//头结点后继 指向 p
            p->front=h;//p的前驱 指向 头节点
            h=h->next;//头指针后移
        }
    }
    //输出
    while(h)
    {
        if(h!=head)//h,前移
        {
            if(h->front)
                printf("%d ",h->data);
            else
                printf("%d\n",h->data);
            h=h->front;
        }
        else
            h=h->front;
    }
    
    while(q)
    {
        if(q!=head)//q,后移
        {
            if(q->next)
                printf("%d ",q->data);
            else
                printf("%d\n",q->data);
            q=q->next;
        }
        else
            q=q->next;
    }
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值