数据结构荣誉课-第六次实验-解题报告

这篇博客是关于数据结构课程的实验解题报告,主要包括高精度数加法、二叉树加权距离、修轻轨问题以及动态数据结构的设计。在高精度数加法中,博主介绍了如何用数组存储高精度数并进行计算,强调了进位和数组大小的处理。在二叉树加权距离部分,博主解释了如何计算加权距离以及找到最近公共祖先的方法。修轻轨问题中,博主提出了利用Kruskal算法求最少施工天数的策略。最后,博主讨论了如何设计动态数据结构,特别是如何利用单调队列高效实现插入、删除、取反和取最大值操作。
摘要由CSDN通过智能技术生成

一、高精度数加法

题目

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

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

输入格式:

第1行,1个整数N,表示高精度整数的个数,(1≤N≤10000)。

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

输出格式:

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

输入样例:

  • 3
  • 12345678910
  • 12345678910
  • 12345678910

输出样例:

  • 37037036730

思路

  1. [高精度数的储存]
    题目中已经给出了提示,我们可以用数组储存高精度数,其中数组的每位储存高精度的若干位,这里我选择的是将高精度数的每5位作为一个单位储存在一个数组的结点中(因为害怕每1位储存之后,增加计算次数导致超时)。例如将“37037036730”储存成“3” “70370” “36730”。
  2. [高精度数的计算]
    计算的时候,可以先让数组中对应的位直接做加法,接着遍历数组,将数组中每位中数值超过5位的部分进位给前一位。
    =>例如计算:[333][33333]+[777][77777]:
    ①数组中对应的位直接相加得[1110][111110]
    ②将数组中每位中数值超过5位的部分([1110][111110])进位给前一位得[1111][11110]
  3. [需要注意的细节]
    ①最高位仍有可能会产生进位,所以int Num[]数组要开21位,而不是20位。
    ②最开始高精度数字肯定是要先读进char []数组中,接着按位转换成int []。转化过程中要注意从后往前转换,即对于char []=“123456789”,要先将(char [])"56789"转化成(int)[56789]。
    ③输出时,要注意存在这样的情况:若计算的答案为55200212,根据本思路,最终储存答案的int []中的内容应该为:[552][212],若直接输出的话,答案为55212,因此输出时要注意补0。(这也是我一直WA的原因)

参考代码

#include "iostream"
#include "cstring"
using namespace std;

int Num[21];//储存每段的高精度数字
int Multiple[5]={
   1,10,100,1000,10000};//字符串转整数时,每位字符转换成整数时乘的倍数不一样,这里就依次枚举了

char str[101];

int N;

int main()
{
   

	cin>>N;

	for(int i=1;i<=N;i++)
	{
   
		cin>>str;
		int len=strlen(str);

		int k=0;//记录当前转化成的整数的位数,每转化5位储存一位
		int j=len-1;//从char数组最后往前转换
		int sum=0;//记录转化的整数大小
		int index=0;//记录转化了多少整数
		while(j>=0)
		{
   
			sum+=(str[j]-'0')*Multiple[k];//注意每位×的倍数不一样
			k++;//每转化1位,k+1
			if(k==5)//如果已经转化了5位,存入数组
			{
   
				Num[index++]+=sum;

				sum=0;//恢复sum和k
				k=0;
			}
			j--;
		}
		if(sum)//将最后不满5位的数字存入(如果sum=0则没有不满5位的数字)
			Num[index]+=sum;
	}

	int x=0;//记录第一个不为0的数字,即找到接下来输出的最高位
	for(int i=0;i<20;i++)
	{
   
		long tmp=Num[i]/100000;
		Num[i]=Num[i]%100000;//本位取余
		Num[i+1]+=tmp;//向前进位

		if(Num[i+1]>0)//更新最高位
			x=i+1;
	}

	cout<<Num[x--];//最高位不需要补0,单独输出

	while(x>=0)
	{
   
		for(int i=4;i>=0;i--)//依次按位输出,这样可以输出00212
		{
   
			cout<<Num[x]/Multiple[i];
			Num[x]%=Multiple[i];
		}
		x--;
	}
	cout<<endl;
}

二、二叉树加权距离

题目

二叉树结点间的一种加权距离定义为:上行方向的边数×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

思路

  1. 解决本题的关键是正确理解题目的意思(当时我就没读明白)。这里我放一个图来代替语言表达:
    对于下面的二叉树,如果询问9和8:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值