数据结构第六次实验报告

高精度数加法 (100 分)

题目

高精度数是指大大超出了标准数据类型能表示的范围的数,例如10000位整数。很多计算问题的结果都很大,因此,高精度数极其重要。

一般使用一个数组来存储高精度数的所有数位,数组中的每个元素存储该高精度数的1位数字或多位数字。 请尝试计算:N个高精度数的加和。这个任务对于在学习数据结构的你来说应该是小菜一碟。 。

输入格式:
第1行,1个整数N,表示高精度整数的个数,(1≤N≤10000)。

第2至N+1行,每行1个高精度整数x, x最多100位。

输出格式:
1行,1个高精度整数,表示输入的N个高精度数的加和。

输入样例:
在这里给出一组输入。例如:

3
12345678910
12345678910
12345678910

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

37037036730

思路

大数加法,用进位将加后的数存到数组中,注意此题不只是两个加数,而可能是多个加数即可。

代码

#include<bits/stdc++.h>
using namespace std;
int SQuc[10001];
int num[101]={0};
char s[101];
int main(){
    int u;
    int length1;
    int length2;
	scanf("%d\n",&u);
    scanf("%s",s);
    length1=strlen(s);
	int j=1;
	for(int i=length1-1;i>=0;i--){
		SQuc[j]=s[i]-'0';
		j++;
	}
	int ant=0,ent; 
	for(int k=2;k<=u;k++)
	{
		char temp[101];
		scanf("%s",temp);
	    length2=strlen(temp);
		for(int y=0;y<101;y++){
			num[y]=0;
		}
		for(int o=length2-1,j=1;o>=0;o--,j++){
        	num[j]=temp[o]-'0';
    	}
    	if(length1<length2){
    		length1=length2;
		}
        ant=0;
    	for(int i=1;i<=length1;i++){
	    	ent=num[i]+SQuc[i]+ant;
	    	if(ent>9){
		    	ant=ent/10;
		    	SQuc[i]=ent%10;
	    	}
	    	else
	    	{
	    		ant=0;
		    	SQuc[i]=ent;
	    	}
    	}
    	if(ant!=0){
    	     	length1++;
    		    SQuc[length1]=ant%10;

		}
    }
    for(int i=length1;i>=1;i--){
		printf("%d",SQuc[i]);
    }
	return 0;
}

二叉树加权距离 (100 分)

题目

二叉树结点间的一种加权距离定义为:上行方向的变数×3 +下行方向的边数×2 。上行方向是指由结点向根的方向,下行方向是指与由根向叶结点方向。 给定一棵二叉树T及两个结点u和v,试求u到v的加权距离。

输入格式:
第1行,1个整数N,表示二叉树的结点数,(1≤N≤100000)。

随后若干行,每行两个整数a和b,用空格分隔,表示结点a到结点b有一条边,a、b是结点的编号,1≤a、b≤N;根结点编号为1,边从根向叶结点方向。

最后1行,两个整数u和v,用空格分隔,表示所查询的两个结点的编号,1≤u、v≤N。

输出格式:
1行,1个整数,表示查询的加权距离。

输入样例:
在这里给出一组输入。例如:

5
1 2
2 3
1 4
4 5
3 4
输出样例:
在这里给出相应的输出。例如:

8

思路

这道题我用了图论解法,上行边权值赋值为3,下行边权值赋值为2,在转化为求最短路问题跑一遍spfa即可。

代码

#include<bits/stdc++.h>
#define MAX 300001
#define maxa 1000001
using namespace std;
int n;
int dis[MAX],head[MAX];
int tot;
int vis[MAX];
queue<int> q;
struct edge{
	int nxt,to,w;
}e[MAX];
void Csh(int s){
	for(int i=1;i<=n;i++){
		dis[i]=maxa;
		vis[i]=0;
	}
	dis[s]=0;
	q.push(s);
}
void add(int u,int v,int w=0){
	e[++tot].to=v;
	e[tot].nxt=head[u];
	e[tot].w=w;
	head[u]=tot;
}
void Spfa(int s){
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=false;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[v]>dis[u]+e[i].w){
            dis[v]=dis[u]+e[i].w;
            if(!vis[v]){
            vis[v]=1;
            q.push(v);

}
}
}
}
}
int main(){
	cin>>n;
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		add(u,v,2);
		add(v,u,3);
	}
int start;
int end1;
cin>>start>>end1;
	Csh(start);
	Spfa(start);
	cout<<dis[end1];
	return 0;
}

修轻轨 (100 分)

题目

长春市有n个交通枢纽,计划在1号枢纽到n号枢纽之间修建一条轻轨。轻轨由多段隧道组成,候选隧道有m段。每段候选隧道只能由一个公司施工,施工天数对各家公司一致。有n家施工公司,每家公司同时最多只能修建一条候选隧道。所有公司可以同时开始施工。请评估:修建这条轻轨最少要多少天。。

输入格式:
第1行,两个整数n和m,用空格分隔,分别表示交通枢纽的数量和候选隧道的数量,1 ≤ n ≤ 100000,1 ≤ m ≤ 200000。

第2行到第m+1行,每行三个整数a、b、c,用空格分隔,表示枢纽a和枢纽b之间可以修建一条双向隧道,施工时间为c天,1 ≤ a, b ≤ n,1 ≤ c ≤ 1000000。

输出格式:
输出一行,包含一个整数,表示最少施工天数。

输入样例:
在这里给出一组输入。例如:

6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6

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

6

思路

一开始没读懂题目。
这道题应该是一道求最小生成树的问题,但是结束条件改为第一个点和第n个点相连即可结束,所以我使用了克鲁斯卡尔算法,用并查集约束结束条件。

代码

#include <stdio.h>
  #include <string.h>
  #include <algorithm>
  #define MAXN 200000  //顶点个数的最大值
  #define MAXM 200000  //边的个数的最大值
  using namespace std;

  struct edge  //边
 {
     int u, v, w; //边的顶点、权值
 }edges[MAXM]; //边的数组
int a[MAXM];
  int n, m;  //顶点个数、边的个数
 int i, j;  //循环变量
 int Find(int x)
{
	return a[x] == x ? x : a[x] = Find(a[x]);
}
void Union(int  aa, int bb)
{
	int x = Find(aa), y = Find(bb);
	if (x != y)
	{
		a[x] = y;
	}
}
 bool cmp( edge a, edge b ) //实现从小到大排序的比较函数
 {
     return a.w <b.w;
 }
 int main( )
 {
     int u, v, w; //边的起点和终点及权值
     scanf( "%d%d", &n, &m ); //读入顶点个数 n
     for( int i=0; i<m; i++ )
     {
     scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点
     edges[i].u = u; edges[i].v = v; edges[i].w = w;
     }
     for (int i = 1; i <= n; ++i)a[i] = i;
    sort(edges,edges+m,cmp);
     long long ans = 0;
    int cnt=0;
	for (int i = 0; i < m; ++i)
	{
		if (Find(edges[i].u) != Find(edges[i].v))
		{
			ans = edges[i].w;
			Union(edges[i].u, edges[i].v);
		}
		if (Find(1) ==Find(n))break;
	}
	printf("%lld\n", ans);
}


数据结构设计(100 分)

题目

小唐正在学习数据结构。他尝试应用数据结构理论处理数据。最近,他接到一个任务,要求维护一个动态数据表,并支持如下操作:

插入操作(I):从表的一端插入一个整数。

删除操作(D):从表的另一端删除一个整数。

取反操作(R):把当前表中的所有整数都变成相反数。

取最大值操作(M):取当前表中的最大值。

如何高效实现这个动态数据结构呢?

输入格式:
第1行,包含1个整数M,代表操作的个数, 2≤M≤1000000。

第2到M+1行,每行包含1个操作。每个操作以一个字符开头,可以是I、D、R、M。如果是I操作,格式如下:I x, x代表插入的整数,-10000000≤x≤10000000。 。

输出格式:
若干行,每行1个整数,对应M操作的返回值。如果M和D操作时队列为空,忽略对应操作。

输入样例:
在这里给出一组输入。例如:

6
I 6
R
I 2
M
D
M
输出样例:
在这里给出相应的输出。例如:

2
2

思路

AC代码。

代码

#include<bits/stdc++.h>
using namespace std;
const int max1 = 1000002;
int cel;
deque<int> ri, le;
int lazy;
int a[max1];
int cnt;
int del;
int main()
{
scanf("%d",&cel);
char oper[2];
for (int i = 1; i <= cel; ++i)
{
scanf("%s",oper);
if (oper[0] == 'I')
{
cnt+=1;
scanf("%d", &a[cnt]);
if (lazy) 
    a[cnt] = -a[cnt];
int tmp = a[cnt];
while (!ri.empty() && a[ri.back()] >= tmp) 
    ri.pop_back();
ri.push_back(cnt);
while (!le.empty() && a[le.back()] <= tmp) 
    le.pop_back();
le.push_back(cnt);
}
 if (oper[0] == 'R')
{
lazy^= 1;
}
 if (oper[0]== 'D')
{
if (del < cnt) {
del++;
while (!ri.empty() && ri.front() <= del)
    ri.pop_front();
while (!le.empty() && le.front() <= del) 
   le.pop_front();
}
}
if (oper[0] == 'M')
{
if (del < cnt) {
if (lazy)
{
    
printf("%d\n", -a[ri.front()]);
    
}
else
{
    
printf("%d\n", a[le.front()]);
    
}
}
}
}
}


思路

超时代码(70分),可能是遍历的时间过长,但是思路很清晰。

代码

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
deque<int>dq;
int x;
int m;
char s;
void func(char s)
{
	if(s=='I')
	{ cin>>x;
		dq.push_front(x);
	}
	else if(s=='D'&&dq.empty()!=1)
	{
		dq.pop_back();
	}
	else if(s=='R')
	{
		for(deque<int>::iterator it=dq.begin();it!=dq.end();++it)
		*it=(-1)*(*it);
	}
	else if(s=='M'&&dq.empty()!=1)
	{
        int q=-99999999999;
       for(deque<int>::iterator it=dq.begin();it!=dq.end();++it){
        if(*it>=q)
            q=*it;
       }
		cout<<q<<endl;
	}
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>s;
		func(s);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值