JLU数据结构荣誉课——第六次上机实验

JLU数据结构荣誉课——第六次上机实验

7-1 高精度数加法 (100 分)

在这里插入图片描述

题目分析

高精度加法,逆序存,反向输出。c++实验做过。

代码实现

#include<stdio.h>
#include<string.h>
char a[100000],b[102],c[1000000],sum[1000000];
void jiafa(char *a,char *b)//后面那个长一点
{
    int l_a,l_b,i;
    int value_a,value_b,value_sum;
    int t=0;//判断进位
    l_a=strlen(a);
    l_b=strlen(b);
    if(l_b<l_a)
    {
        char m[100000];
        strcpy(m,a);
        strcpy(a,b);
        strcpy(b,m);
    }
    l_a=strlen(a);
    l_b=strlen(b);
    for(i=0;i<l_a;i++)
    {
        value_a=a[i]-'0';
        value_b=b[i]-'0';
        value_sum=value_a+value_b+t;
        if(value_sum>=10)t=1;
        else t=0;
        b[i]=value_sum%10+'0';
    }
    for(;i<l_b;i++)
    {
        if(t==0)break;
        else
        {
            value_b=b[i]-'0'+1;
            if(value_b>=10)t=1;
            else t=0;
            b[i]=value_b%10+'0';
        }
    }
    if(t==1&&b[i]) b[i]=b[i]+1;
    if(t==1&&!b[i])
    {
        b[i]='1';
        b[i+1]=0;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",a);
    int la=strlen(a);
    for(int i=0;i<=la-1;i++)
    {
        c[i]=a[la-1-i];
    }
  //  printf("%s",c);
    for(int i=0;i<n-1;i++)
    {
        char d[102];
        scanf("%s",d);
        int lb=strlen(d);
        for(int j=0;j<=(lb-1)/2;j++)
        {
            int z;
            z=d[j];
            d[j]=d[lb-1-j];
            d[lb-1-j]=z;
        }
        jiafa(d,c);
    }
    int l;
    l=strlen(c);
    for(int i=l-1;i>=0;i--)
    printf("%c",c[i]);
}

7-2 二叉树加权距离 (100 分)

在这里插入图片描述

题目分析

把二叉树当作图处理,父节点到子节点的权值为2,子节点到父节点的权值为3。

如果用dijstra会超时,换成spfa后就行了。

代码实现如下

#include<bits/stdc++.h>
using namespace std;
struct Node
{
    int name;
    int cost;
};

#define Max 100001

vector<Node> Map[Max];
int visited[Max];
int cost[Max];
int path[Max];
queue<Node> que;

int main()
{
    int n,i,j,u;
    cin>>n;
    Node a;
    for(i=1;i<=n;i++)
        cost[i]=1000001;
    for(i=0;i<n-1;i++)
    {
        int t0,t1;
        cin>>t0;
        cin>>t1;
        a.name=t1;
        a.cost=2;
        Map[t0].push_back(a);
        a.name=t0;
        a.cost=3;
        Map[t1].push_back(a);
    }
    int zz1,zz2;
    cin>>zz1;
    cin>>zz2;
    cost[zz1]=0;
    visited[0]=1;
    a.cost=0;
    a.name=zz1;
    que.push(a);
    while(!que.empty())
    {
        a=que.front();
        que.pop();
        visited[a.name]=0;
        for(vector<Node>::iterator k = Map[a.name].begin();k!=Map[a.name].end();k++)
        {
            if(cost[k->name]>cost[a.name]+k->cost)
            {
                cost[k->name]=cost[a.name]+k->cost;
 //               path[k->name]=u;
                if(!visited[k->name])
                {
                    que.push(*k);
                    visited[k->name]=1;
                }
            }
        }
    }
    printf("%d",cost[zz2]);
}

7-3 修轻轨 (100 分)

在这里插入图片描述

题目分析

方法一:
最小生成树问题,这里因为生成后需要延路径寻找路径上的最大值,我用的prim(prim生成最小生成树时能保留路径)。

具体代码

#include<bits/stdc++.h>
using namespace std;
struct Node
{
    int name;
    int cost;
    bool operator<(const Node& a)const
    {
        return cost> a.cost;
    }
};
priority_queue<Node> q;
#define Max 100001

vector<Node> Map[Max];
int visited[Max];
int cost[Max];
int path[Max];
queue<Node> que;

int main()
{
    int m,n,i,j,u;
    scanf("%d",&n);
    scanf("%d",&m);
    Node a;
    for(i=1;i<=n;i++)
        cost[i]=1000002;
    for(i=0;i<m;i++)
    {
        int t0,t1,cost0;
        scanf("%d",&t0);
        scanf("%d",&t1);
        scanf("%d",&cost0);
        a.name=t1;
        a.cost=cost0;
        Map[t0].push_back(a);
        a.name=t0;
        Map[t1].push_back(a);
    }
    visited[1]=1;
    cost[1]=0;
    for(vector<Node>::iterator k = Map[1].begin();k!=Map[1].end();k++)
    {
        a.name=k->name;
        a.cost=k->cost;
        q.push(a);
        path[a.name]=1;
        cost[a.name]=a.cost;
    }
    for(j=1;j<n&&!q.empty();j++)
    {
        int l=1000001;
        a=q.top();
        q.pop();
        while(visited[a.name]&&!q.empty())
        {
            a=q.top();
            q.pop();
        }
        u=a.name;
        if(u==n)break;
 //       printf("%d",u);
        visited[u]=1;
        for(vector<Node>::iterator k = Map[u].begin();k!=Map[u].end();k++)
        {
            int v=k->name;
            if(k->cost<cost[v]&&visited[v]==0)
            {
                a.name=v;
                a.cost=k->cost;
                q.push(a);
                cost[v]=k->cost;
                path[v]=u;
            }
        }
    }
    int zz,Max_=0;
    for(zz=n;zz!=1;zz=path[zz])
    {
        if(Max_<cost[zz])Max_=cost[zz];
        printf("%d\n",zz);
    }
    printf("%d",Max_);
}

方法二:
还是使用spfa算法,将 “松弛” 操作改变,每一个点的cost中记录到次点这条路径上的最大边权,到一个新顶点后,将这个顶点的cost与max(上一个顶点的cost,两顶点间的权值)比较,取较小者。

具体代码实现如下

#include<bits/stdc++.h>
using namespace std;
struct Node
{
    int name;
    int cost;
};
#define Max 100001

vector<Node> Map[Max];
int visited[Max];
int cost[Max];
int path[Max];
queue<Node> que;

int main()
{
    int m,n,i,j,u;
    scanf("%d",&n);
    scanf("%d",&m);
    Node a;
    for(i=1;i<=n;i++)
        cost[i]=1000001;
    for(i=0;i<m;i++)
    {
        int t0,t1,cost0;
        scanf("%d",&t0);
        scanf("%d",&t1);
        scanf("%d",&cost0);
        a.name=t1;
        a.cost=cost0;
        Map[t0].push_back(a);
        a.name=t0;
        Map[t1].push_back(a);
    }
    cost[1]=0;
    visited[1]=1;
    a.cost=0;
    a.name=1;
    que.push(a);
    while(!que.empty())
    {
        a=que.front();
        que.pop();
        visited[a.name]=0;
        for(vector<Node>::iterator k = Map[a.name].begin();k!=Map[a.name].end();k++)
        {
            if(cost[k->name]>max(cost[a.name],k->cost))
            {
                cost[k->name]=max(cost[a.name],k->cost);
 //               path[k->name]=u;
                if(!visited[k->name])
                {
                    que.push(*k);
                    visited[k->name]=1;
                }
            }
        }
    }
    printf("%lld",cost[n]);
}

7-4 数据结构设计I (100 分)

在这里插入图片描述

题目分析

因为取最大值,我想到了使用优先队列。对于R操作,如果遍历所有数据取反肯定是行不通的,这里使用一个标记r记录R操作的次数,如果r为奇数,则进行I操作时取反再压入。

这样一来我们就需要维护两个优先队列,一个取最大值,一个取最小值(当r为奇数时)。

但是同时也会有删除操作,这个怎么实现呢?我们不正真地删除,而是引入下标,top和rear,删除元素,top++,加入元素,rear++。同时在优先队列中保存数值的同时我们保存他的下标,从优先队列中取出一个数时,如果其下标小与top代表该数已经被删除,循环弹出,直到数字合法(未被删除)

具体代码实现如下

#include<bits/stdc++.h>
using namespace std;
struct Node1
{
    int value;
    int num;
    bool operator<(const Node1& a)const
    {
        return value< a.value;
    }
};
struct Node2
{
    int value;
    int num;
    bool operator<(const Node2& a)const
    {
        return value> a.value;
    }
};
priority_queue<Node1> q1;//最大值
priority_queue<Node2> q2;//最小值
int top,rear,i,j,k,r,m;
Node1 a1;
Node2 a2;
char ch;
int main()
{
    scanf("%d",&m);
    getchar();
    for(i=0;i<m;i++)
    {
        scanf("%s",&ch);
        if(ch=='I')
        {
            int t;
            scanf("%d",&t);
            if(r%2==1)t=-t;
            a1.num=rear;
            a1.value=t;
            q1.push(a1);
            a2.num=rear;
            a2.value=t;
            q2.push(a2);
            rear++;
        }
        else if(ch=='R')
        {
            r++;
        }
        else if(ch=='D'&&top<rear)
        {
            top++;
        }
        else if(ch=='M'&&top!=rear)
        {
            if(r%2==0)
            {
                Node1 zz=q1.top();
                while(zz.num<top)
                {
                    q1.pop();
                    if(q1.empty())break;
                    zz=q1.top();
                }
                if(k!=0)
                {
                	printf("\n");
				}
				k++;
                if(!q1.empty())printf("%d",zz.value);
            }
            else
            {
                 Node2 zz=q2.top();
                while(zz.num<top)
                {
                    q2.pop();
                    if(q2.empty())break;
                    zz=q2.top();
                }
                if(k!=0)
                {
                	printf("\n");
				}
				k++;
                if(!q2.empty())printf("%d",-zz.value);
            }
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值