C++数据结构实验第三次作业(2022--矿大)

问题 A: 任意二叉树的层次遍历

题目描述

有若干个节点,每个节点上都有编号,把这些节点随意地构成二叉树,请编程输出该二叉树的层次遍历序列。

输入

第一行是n(n小于100),表示有n个节点,每个节点按从1到n依次编号。第一行后有n行,每行三个正整数i、l、r,分别表示节点i及对应的左右孩子的编号,如果不存在孩子则以-1表示。三个整数之间用一个空格隔开。

输出

输出该二叉数的层次遍历序列。

样例输入
4
1 2 4
3 1 -1
2 -1 -1
4 -1 -1
样例输出
3 1 2 4
#include<iostream>
using namespace std;
#include<queue>
struct Node{
	int left,right;
};
void preOrder(Node ntr[],int k){
	cout<<k<<" ";
	if(ntr[k].left!=-1) preOrder(ntr,ntr[k].left);
	if(ntr[k].right!=-1) preOrder(ntr,ntr[k].right);
}
void levelOrder(Node ntr[],int k){
	queue<int> Q;
	Q.push(k);
	while(!Q.empty()){
		cout<<Q.front()<<" ";
		if(ntr[Q.front()].left!=-1) Q.push(ntr[Q.front()].left);
		if(ntr[Q.front()].right!=-1) Q.push(ntr[Q.front()].right);
		Q.pop();
	}
	cout<<endl;
}
void Show(Node ntr[],int root[],int n){
	for(int i=1;i<=n;i++){
		if(root[i]){
			levelOrder(ntr,i);
		}
	}
}
int main(){
	int n;
	cin>>n;
	Node* ntr=new Node[n+1];
	int* root=new int[n+1];
	for(int i=1;i<=n;i++) root[i]=1;
	int x,y,z;
	for(int i=0;i<n;i++){
		cin>>x>>y>>z;
		ntr[x].left=y;
		ntr[x].right=z;
		if(y!=-1)root[y]=0;
		if(z!=-1)root[z]=0;
	}
	Show(ntr,root,n);
	return 0;
}

问题 B: 小根堆的判定

题目描述

堆是以线性连续方式存储的完全二叉树,小根堆的每一个元素都不大于其左右孩子,现在给你n个完全二叉树数组存储序列,请编程判定相应完全二叉树数组存储序列是否为小根堆。

输入

第一行n(n<100),表示有n组测试用例。后边的n行,每一行都是相应完全二叉树数组存储序列(序列最长为100)。

输出

对应相应完全二叉树数组存储序列,判定为小根堆的输出True,否则输出False。

样例输入
2
30 26 27 88
5 6 7 8 9 10
样例输出
False
True
#include<iostream>
using namespace std;
int judge(int s[],int count){
	for(int i=0;i<count;i++){
		if((2*i+1)<count&&s[i]>s[2*i+1]||(2*i+2)<count&&s[i]>s[2*i+2]) return 0;		
	}
	return 1;
}
int main(){
	int n;
	cin>>n;
	int test[100];
	int k,count;
	int ans[n];
	for(int i=0;i<n;i++){
		count=0;
		while(cin>>k){
			test[count++]=k;
			if(cin.get()== '\n') break;
		}
		ans[i]=judge(test,count);
	}
	for(int i=0;i<n;i++){
		if(ans[i]==0){
			cout<<"False"<<endl;
		}else if(ans[i]==1){
			cout<<"True"<<endl;
		}
	}
	return 0;
}

问题 C: 最小堆的形成

题目描述

现在给你n个结点的完全二叉树数组存储序列,请编程调整为最小堆,并输出相应最小堆的存储序列。

输入

第一行是n,第二行是n个结点的完全二叉树数组存储序列。

输出

输出相应最小堆的存储序列。

样例输入
8
53 17 78 23 45 65 87 9
样例输出
9 17 65 23 45 78 87 53
#include<iostream>
using namespace std;
void siftUp(int heap[],int start){
	int j=start,i=(j-1)/2,temp=heap[j];
	while(j>0){
		if(heap[i]<=temp) break;
		else{
			heap[j]=heap[i];j=i;i=(i-1)/2;
		}
	}
	heap[j]=temp;
}
int main(){
	int n;
	cin>>n;
	int heap[n];
	for(int i=0;i<n;i++){
		cin>>heap[i];
		siftUp(heap,i);
	} 
	for(int i=0;i<n;i++){
		cout<<heap[i]<<" ";
	}
	cout<<endl;
	return 0;
}

问题 D: 无向图的深度优先搜索

题目描述

已知一个无向图G的顶点和边,顶点从0依次编号,现在需要深度优先搜索,访问任一邻接顶点时编号小的顶点优先,请编程输出图G的深度优先搜索序列。

输入

第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行2个数,分别表示一个边的两个顶点。

输出

该图从0号顶点开始的深度优先搜索序列。

样例输入
5 5
0 1
2 0
1 3
1 4
4 2
样例输出
0 1 3 4 2
#include<iostream>
#include<queue> 
using namespace std;
class Graph{
	private:
		int n;
		int** edge;
	public:
		Graph(int n):n(n){
			edge=new int*[n];
			for(int i=0;i<n;i++){
				edge[i]=new int[n];
				for(int j=0;j<n;j++){
					if(i==j)edge[i][j]=0;
					else edge[i][j]=-1;
				}
			}	
		}
		void insertEdge(int v1,int v2){
			edge[v1][v2]=1;
			edge[v2][v1]=1;
		}
		int getFirst(int v1){
			for(int i=0;i<n;i++){
				if(edge[v1][i]==1){
					return i;
				} 
			}
			return -1;
		}
		int getNext(int v1,int v2){
			for(int i=v2+1;i<n;i++){
				if(edge[v1][i]==1){
					return i;
				} 
			}
			return -1;
		}
		void DFS(int v,bool visited[]){
			cout<<v<<" ";
			visited[v]=true;
			int w=getFirst(v);
			while(w!=-1){
				if(visited[w]==false)DFS(w,visited);
				w=getNext(v,w); 
			}
			
		}
		void DFS(int v){
			bool* visited=new bool[n];
			for(int i=0;i<n;i++) visited[i]=false;
			DFS(v,visited);
		}
		void BFS(int v){
			bool* visited=new bool[n];
			for(int i=0;i<n;i++)visited[i]=false;
			cout<<v<<" ";
			visited[v]=true;
			queue<int> Q;
			Q.push(v);
			while(!Q.empty()){
				v=Q.front();
				Q.pop();
				int w=getFirst(v);
				while(w!=-1){
					if(visited[w]==false){
						cout<<w<<" ";
						visited[w]=true;
						Q.push(w);
					}
					w=getNext(v,w);
				}
			}
		}
};

int main(){
	int n,k;
	cin>>n>>k;
	Graph G(n);
	int v1,v2;
	for(int i=0;i<k;i++){
		cin>>v1>>v2;
		G.insertEdge(v1,v2);
	}
	G.DFS(0);
	//G.BFS(0);
	return 0;
}

问题 E: 无向图的广度优先搜索

题目描述

已知一个无向图G的顶点和边,顶点从0依次编号,现在需要广度优先搜索,访问任一邻接顶点时编号小的顶点优先,请编程输出图G的广度优先搜索序列。

输入

第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行2个数,分别表示一个边的两个顶点。

输出

该图从0号顶点开始的广度优先搜索序列。

样例输入
5 5
0 1
2 0
1 3
1 4
4 2
样例输出
0 1 2 3 4
#include<iostream>
#include<queue> 
using namespace std;
class Graph{
	private:
		int n;
		int** edge;
	public:
		Graph(int n):n(n){
			edge=new int*[n];
			for(int i=0;i<n;i++){
				edge[i]=new int[n];
				for(int j=0;j<n;j++){
					if(i==j)edge[i][j]=0;
					else edge[i][j]=-1;
				}
			}	
		}
		void insertEdge(int v1,int v2){
			edge[v1][v2]=1;
			edge[v2][v1]=1;
		}
		int getFirst(int v1){
			for(int i=0;i<n;i++){
				if(edge[v1][i]==1){
					return i;
				} 
			}
			return -1;
		}
		int getNext(int v1,int v2){
			for(int i=v2+1;i<n;i++){
				if(edge[v1][i]==1){
					return i;
				} 
			}
			return -1;
		}
		void DFS(int v,bool visited[]){
			cout<<v<<" ";
			visited[v]=true;
			int w=getFirst(v);
			while(w!=-1){
				if(visited[w]==false)DFS(w,visited);
				w=getNext(v,w); 
			}
			
		}
		void DFS(int v){
			bool* visited=new bool[n];
			for(int i=0;i<n;i++) visited[i]=false;
			DFS(v,visited);
		}
		void BFS(int v){
			bool* visited=new bool[n];
			for(int i=0;i<n;i++)visited[i]=false;
			cout<<v<<" ";
			visited[v]=true;
			queue<int> Q;
			Q.push(v);
			while(!Q.empty()){
				v=Q.front();
				Q.pop();
				int w=getFirst(v);
				while(w!=-1){
					if(visited[w]==false){
						cout<<w<<" ";
						visited[w]=true;
						Q.push(w);
					}
					w=getNext(v,w);
				}
			}
		}
};

int main(){
	int n,k;
	cin>>n>>k;
	Graph G(n);
	int v1,v2;
	for(int i=0;i<k;i++){
		cin>>v1>>v2;
		G.insertEdge(v1,v2);
	}
	//G.DFS(0);
	G.BFS(0);
	return 0;
}

问题 F: 最小生成树

题目描述

已知一个无向图G的顶点和边,顶点从0依次编号,请编程输出图G的最小生成树对应的边权之和。

输入

第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行3个数,分别表示一个边的两个顶点和该边的权值。

输出

最小生成树对应的边权之和。

样例输入
4 5
0 1 6
0 2 9
2 1 12
1 3 10
3 2 3
样例输出
18
#include<iostream>
using namespace std;
#define Max 100000
class UFset{
	private:
		int* parent;
		int size;
	public:
		UFset(int n):size(n){
			parent=new int[size];
			for(int i=0;i<size;i++)parent[i]=-1;
		}
		int Find(int x){
			while(parent[x]>=0) x=parent[x];
			return x;
		}
		void Union(int r1,int r2){
			parent[r1]+=parent[r2];
			parent[r2]=r1;
		}
}; 
class Node{
public:
	int v1,v2,value;
	Node(int v1=-1,int v2=-1,int value=0){
		v1=v1;
		v2=v2;
		value=value;
	}
	Node(const Node& n){
		v1=n.v1;
		v2=n.v2;
		value=n.value;
	}
};
class Graph{
	private:
		int n;
		int* vertex;
		int** edge;
		void findMin(Node& newnode){
			int x=0,y=1;
			for(int i=0;i<n;i++){
				for(int j=i+1;j<n;j++){
					if(edge[i][j]<edge[x][y]&&edge[i][j]!=0){
						x=i;y=j;
					} 
				}
			}
			newnode.v1=x;
			newnode.v2=y;
			newnode.value=edge[x][y];
			edge[x][y]=Max;
			edge[y][x]=Max;
		}
	public:
		Graph(int n):n(n){
			vertex=new int[n];
			edge=new int*[n];
			for(int i=0;i<n;i++){
				vertex[i]=i;
				edge[i]=new int[n];
				for(int j=0;j<n;j++){
					if(i==j)edge[i][j]=0;
					else edge[i][j]=Max;
				}
			}
		}
		void insertEdge(int v1,int v2,int value){
			edge[v1][v2]=value;
			edge[v2][v1]=value;
		} 
		void show(){
			for(int i=0;i<n;i++){
				for(int j=0;j<n;j++){
					cout<<edge[i][j]<<" ";
				}
				cout<<endl;
			}
		}
		int Kruskal(){
			UFset F(n);
			int count=0,sum=0;
			int u,v;
			Node newnode;
			while(count<n-1){
				findMin(newnode); 
				u=F.Find(newnode.v1);
				v=F.Find(newnode.v2);
				if(u!=v){
					F.Union(u,v);
					sum+=newnode.value;
					count++;
				}
			}
			return sum;
		}
};
int main(){
	int n,k;
	cin>>n>>k;
	Graph G(n);
	int v1,v2,value;
	for(int i=0;i<k;i++){
		cin>>v1>>v2>>value;
		G.insertEdge(v1,v2,value);
	}
	//G.show();
	int min=G.Kruskal();
	cout<<min<<endl;
	return 0;
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值