数据结构第六次上机实验
一、高精度数:
题意:实现高精度数的加法运算。
思路:用数组来存放数的所有数位,为了进位方便,我们选择倒叙存储。
完整代码:
#include<bits/stdc++.h>
using namespace std;
int const max0=2000;
int a[max0],b[max0],sum[max0];
int main()
{ for(int i=0;i<max0;i++)
{
sum[i]=0;
}
int N;
cin>>N;
int start=max0-1;
for(int i=0;i<N;i++)
{
char buffer[150];
scanf("%s",buffer);
int len=strlen(buffer);
int ed=len-1;
// cout<<len;
for(int i=0;i<len;i++)
{sum[i]=sum[i]+buffer[ed--]-'0';
// cout<<sum[i];
}
}
// cout<<endl;
for(int i=0;i<max0;i++)
{
if(sum[i]>=10)
{ int chu=sum[i]/10;
sum[i]=sum[i]%10;
sum[i+1]+=chu;
}
}
int j=max0-1;
int k=0;
while(sum[j]==0)
{
k++;
j--;
}
// cout<<k<<endl;
for(int i=max0-k-1;i>=0;i--)
{
cout<<sum[i];
}
return 0;
}
二、二叉树加权距离
题意:两个结点的加权距离,即上溯到根节点后下溯到目标节点,或直接上溯目标节点,或下溯目标节点。
思路:我们都知树是一种特殊的图,根据题意,我们在建图(树)过程中,两个结点u,v之间可同时建立两条有向边,u->v的边权为2,v->u的边权为3,以此来达到上溯代价为3,下溯代价为2的目的。然后一遍dijkstra(采用了堆优化)。即可。
代码:
1、建图
struct edge{
int to;
int cost;
int parent;
edge(int t,int c):to(t),cost(c){
}
};
for(int i = 0;i<m;i++){
scanf("%d%d",&a,&b);
g[a].push_back(edge(b,2));
g[b].push_back(edge(a,3));
}
2、完整代码
#include<bits/stdc++.h>//该算法适用于稀疏图,稠密图,用于弗洛伊德
#define INF 100000005
#define MAX 100006
using namespace std;
typedef pair<int,int> P;
struct edge{
int to;
int cost;
int parent;
edge(int t,int c):to(t),cost(c){
}
};
int length(int s0);
const int N = 100006;
vector<edge> g[N];
int dis[100][100],cd[100000]; //距离
int n,m; //n个点 m条边
//int path[100][100];//最小生成路的长度
int path[100000];
int D[100000];
void Dijkstra(int s){
static int countdij=0;
priority_queue<P,vector<P>,greater<P> > que; //小端优先队列
fill(D,D+100005,INF);//注意必须初始化为最大
D[s] = 0;
if(s==0)
for(int i=0;i<n;i++)
path[i]=-1;
que.push(P(0,s));
while(!que.empty())
{
P p = que.top();
que.pop();
int v = p.second;
if(D[v] < p.first) continue; //说明该点无需重复
for(int i = 0;i<g[v].size();i++) {
//遍历所有后续边
edge e = g[v][i];
int to = e.to;
int cost = e.cost;
if(D[to] > D[v] + cost){
D[to] = D[v] + cost;
que.push(P(D[to],to));
}
}
}
}
int main(){
int s=1,u,v;
cin>>n;//m为边数,n为点数
m=n-1;
int a,b,d;
//Vector<edge> g[MAX]的初始化
for(int i = 0;i<MAX;i++) {
g[i].clear();
}
for(int i = 0;i<m;i++){
scanf("%d%d",&a,&b);
g[a].push_back(edge(b,2));
g[b].push_back(edge(a,3));
}
cin>>u>>v;
Dijkstra(u);
int k;
cout<<D[v];
//cout<<"0";
cout<<endl;
return 0;
}
三、修轻轨
题意:求修建由1到n的轻轨最少修建时间
思路:该题可由最短路问题求解。采用kruskal和并查集判断求解。我们将所有的交通枢纽抽象成一个点,每个点代表一个集合,每次合并集合时我们判断1,n是否在一个集合里。若在则这次加的边即为所求,若不在则继续加边。这题时间点卡的很好,并查集如果不按秩合并的话会超时。
代码:
1、关键代码
void kruskal()
{
int n,m0;
int l=0;
cin>>n>>m0;
for(int k=0;k<m0;k++)
{ int i,j,weight=0;
cin>>i>>j>>weight;
E[l].head=i;
E[l].tail=j;
E[l].cost=weight;
l++;
}
for(int i=1;i<=n;i++)
father[i]=i;
for(int i=1;i<=n;i++)
{
rank0[i]=0;
}
int T=n;
m=l;
sort(E,E+m,cmp);
int j=0,ss=0;
int count=0;
while(T>1)
{
int v1=E[j].head;
int v2=E[j].tail;
int cost=E[j].cost;
if(find_set(v1)!=find_set(v2))
{
TE[count].head=v1;
TE[count].tail=v2;
TE[count].cost=cost;
count++;
Union(v1,v2);
T--;
}
if(find_set(1)==find_set(n))
{
ss=cost;
break;
}
j++;
}
// for(int i=1;i<n;i++)
// cout<<make_set[i]<<" ";
cout<<ss;
}
2、完整代码
#include<vector>
#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
typedef vector<vector<int>> Mat;
const int max0=99999;
struct node
{
int head;
int tail;
int cost;
}E[200010],TE[200010];
int make_set[1001],m;
int rank0[200100];
int cmp(node a,node b);
int find_set(int x);
int father[100000];
void Union(int x,int y);
void kruskal();//克鲁斯卡尔求最小生成树:适用于边稀疏图
void kruskal()
{
int n,m0;
int l=0;
cin>>n>>m0;
for(int k=0;k<m0;k++)
{ int i,j,weight=0;
cin>>i>>j>>weight;
E[l].head=i;
E[l].tail=j;
E[l].cost=weight;
l++;
}
for(int i=1;i<=n;i++)
father[i]=i;
for(int i=1;i<=n;i++)
{
rank0[i]=0;
}
int T=n;
m=l;
sort(E,E+m,cmp);
int j=0,ss=0;
int count=0;
while(T>1)
{
int v1=E[j].head;
int v2=E[j].tail;
int cost=E[j].cost;
if(find_set(v1)!=find_set(v2))
{
TE[count].head=v1;
TE[count].tail=v2;
TE[count].cost=cost;
count++;
Union(v1,v2);
T--;
}
if(find_set(1)==find_set(n))
{
ss=cost;
break;
}
j++;
}
// for(int i=1;i<n;i++)
// cout<<make_set[i]<<" ";
cout<<ss;
}
int cmp(node a,node b)
{
return a.cost<b. cost;
}
int find_set(int v)
{
if(father[v]==v) return v;
return find_set(father[v]);
}
void Union( int x , int y)
{
int fx = find_set(x);
int fy = find_set(y);
if(rank0[fx]<=rank0[fy])
{
father[fx]=fy;
if(rank0[fx]==rank0[fy])
rank0[fy]++;
}
else {
father[fy]=fx;
}
}
int main()
{
kruskal();
return 0;
}
四、数据结构设计
题意:建立一个能够对数据高效的进行插入,删除,取反,取最大的动态数据表。
思路:本题太良心了,纯暴力方法都可拿70分,若想拿满分,还需要对取反操作进行优化。我采用了multiset和一个取反标志flag。每取一次反,flag++。
代码:
1、暴力求解代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000;
const int INF=99999999;
int q[1000000],maxs[400000],sum=0;
inline int maxq(int *q,int f,int r);
int main()
{ char a;
int r=0,f=0;
int T=0,k=0;
cin>>T;
for(int i=0;i<T;i++)
{
cin>>a;
if(a=='I')
{
int x;
cin>>x;
q[r]=x;
r=(r+1)%maxn;
}
else if(a=='D')
{ if(f==r) continue;
else f=(f+1)%maxn;
}
else if(a=='R')
{
int s=f;
for(;s!=r+1;s++)
{
q[s]=-1*q[s];
}
}
else if(a=='M')
{ int max0;
if(f==r) continue;
else {
max0=maxq(q,f,r);
maxs[sum++]=max0;
}
}
}
cout<<sum;
for(int i=0;i<sum;i++)
{
cout<<maxs[i];
if(i<sum-1) cout<<"\n";
}
return 0;
}
int maxq(int q[],int f,int r)
{
int m=-1*INF;
for(;f!=r;f++)
{
if(q[f]>m)
m=q[f];
}
return m;
}
2、优化后的代码:
1)、关键代码-----取反和取最大操作
if(a[0]=='D')
{ if(q.empty()) continue;
auto aa=setq.find(q.front());
setq.erase(aa);
q.pop();
}
else if(a[0]=='R')
{
flag++;
}
else if(a[0]=='M')
{ if(q.empty()) continue;
if(flag%2!=0)
{int temp=*(setq.begin());
printf("%d\n",-temp);
}
else {
int temp=*(setq.rbegin());
printf("%d\n",temp);
}
}
2)、完整代码
#include<bits/stdc++.h>
#include<stdio.h>
using namespace std;
const int maxn=200000;
const int INF=99999999;
multiset<int>setq;
queue<int>q;
int main()
{ char a[10];
int T,flag=0;
int x;
cin>>T;
for(int i=0;i<T;i++)
{
scanf("%s",a);
if(a[0]=='I')
{
scanf("%d",&x);
if(flag%2!=0)
{
x=-x;
}
q.push(x);
setq.insert(x);
}
else if(a[0]=='D')
{ if(q.empty()) continue;
auto aa=setq.find(q.front());
setq.erase(aa);
q.pop();
}
else if(a[0]=='R')
{
flag++;
}
else if(a[0]=='M')
{ if(q.empty()) continue;
if(flag%2!=0)
{int temp=*(setq.begin());
printf("%d\n",-temp);
}
else {
int temp=*(setq.rbegin());
printf("%d\n",temp);
}
}
}
return 0;
}