数据结构实验3:生成最小树

数据结构实验3 :图的遍历生成树

实验内容及原理

  1. 键盘输入n个顶点和m条边(6<=n<=16,n-1<=m<=20)及相应权重,建立图的邻居矩阵和邻接表的存储形式,并输出该邻接矩阵和邻接表。
  2. 用Prim算法求其最小生成树。函数 void Prim(AMGraph G, VerTexType u) 以及输出边集数组的函数 void PrintEdge(Edgeset Sedge, int n)。
  3. 编写测试程序(即主函数),通过调用上述函数首先建立并输出无向带权图,然后生成最小生成树并输出(即输出边集)。

分析

实验内容比较简单,涉及到的知识主要有:图的存储,遍历,生成最小树算法,并且图的存储要用两种方法实现方式:邻接矩阵和邻接表。
prim 算法主要思路:维护两个集合:当前已经收录的结点集V{} , 和当前v中的结点直接相连的边的集合E{}。 每次从E{}中取出终点不在V{},并且长度最短的一条边,并更新V{},E{},直至全部结点都收录到E{}。从E{}中取出最短的一条边,简单实现可以用数组加遍历的方式,进阶方式是使用优先队列,可以减少时间复杂度和代码长度。


结构表示
//边结构
struct edge{
	int from;
	int to;
	int len;
	edge(int f, int t, int l){
		from = f; to = t; len = l;
	}
};
//用于定义优先队列对节点的排序方式
struct cmp{
	bool operator()(edge &a, edge &b){
		return a.len > b.len;
	}
};
//结点结构
struct grap_node{
	int val;
	vector<edge>next;
};
邻接表实现

//无向图1,以邻接表为存储形式
class GRAP_one{
	vector<grap_node> data;
public:
	//展示邻接表
	void display(){
		cout << "================= display ===============\n";
		for (int i = 0; i < data.size(); i++){
			cout << i+1;	//还原为输入时的数值
			for (int y = 0; y < data[i].next.size(); y++){
				printf(" -> %d", data[i].next[y].to+1);
			}
			cout << endl;
		}
		cout << "==========================================\n";
	}
	//初始化邻接表
	void init(){
		cout << "Please input the node number and edge number : >";
		int n, e;
		cin >> n >> e;
		data.resize(n);
		cout << "Please input all edge with format: from  to  length : \n";
		for (int i = 0; i < e; i++){
			int f, t, l;
			scanf("%d%d%d", &f, &t, &l);
			f--, t--;	//输入结点以1为起点,保存时以0为起点
			data[f].next.push_back({f, t, l });
			data[t].next.push_back({t, f, l });
		}
		cout << "input over.... \n";
	}
	//生成并展示最小生成树
	void prim(){
		priority_queue<edge,vector<edge>,cmp>epq; 
		set<int> nset;
		set<int>::iterator it;
		nset.insert(0);
		for (int i = 0; i < data[0].next.size(); i++){
			epq.push({ 0, data[0].next[i].to, data[0].next[i].len });
		}
		while (epq.empty() == false){
			edge temp = epq.top();
			epq.pop();
			it = nset.find(temp.to);
			if (it != nset.end()){	
				continue;
			}
			printf("%d ---> ( %d ) ---> %d \n", temp.from+1, temp.len, temp.to+1);
			nset.insert(temp.to);
			for (int i = 0; i < data[temp.to].next.size(); i++){
				epq.push({ temp.to, data[temp.to].next[i].to, data[temp.to].next[i].len });
			}
		}
	}
};
邻接矩阵实现
//无向图2,以矩阵为存储形式
class GRAP_two{
private:
	int **data;	//邻接矩阵
	int nn, en;	//node number ,edge number
public:
	//初始化图
	void init(){
		cout << "Please input node number, edge number: >";
		scanf("%d %d", &nn, &en);
		data = (int**)malloc(sizeof(int*)*nn);	//申请内存
		for (int i = 0; i < nn; i++){
			data[i] = (int*)malloc(sizeof(int)*nn);
			memset(data[i], 0, sizeof(int)*nn);
		}
		cout << "Please input data with format : from to lenght \n";
		for (int i = 0; i < en; i++){
			int f, t, l;
			scanf("%d%d%d", &f, &t, &l);
			data[f-1][t-1] = data[t-1][f-1] = l;
		}
		cout << "input data over... \n\n";
	}
	//展示邻接矩阵
	void display(){
		cout << "====================== Display of grap ============" << endl;
		for (int i = 0; i < nn; i++){
			for (int y = 0; y < nn; y++){
				printf("   %d   ", data[i][y]+1);
			}
			cout << endl;
		}
		cout << "===================================================\n\n";
	}
	void prim(){
		priority_queue<edge, vector<edge>, cmp>epq;
		set<int> nset;
		set<int>::iterator it;
		nset.insert(0);
		for (int i = 0; i < nn; i++){
			if (data[0][i] == 0 ) continue;
			epq.push({ 0, i, data[0][i]});
		}
		while (epq.empty() == false){
			edge temp = epq.top();
			epq.pop();
			it = nset.find(temp.to);
			if (it != nset.end()){ 
				continue;
			}
			printf("%d --->( %d ) ---> %d \n", temp.from + 1, temp.len, temp.to +1);
			nset.insert(temp.to);
			for (int i = 0; i < nn; i++){
				if (data[temp.to][i] == 0) continue;
				epq.push({ temp.to, i, data[temp.to][i] });
			}
		}
	}
};
测试代码
//测试 GRAP_one 功能
void test_GRAP_one(){
	GRAP_one grap;
	grap.init();
	grap.display();
	grap.prim();
}

//测试 GRAP_two 功能
void test_GRAP_two(){
	GRAP_two grap;
	grap.init();
	grap.display();
	grap.prim();
}

int main(){
	test_GRAP_one();
	//test_GRAP_two();
	return 0;
}

##### 运行结果

模拟数据
6 8
1 2 8
1 3 7
3 4 2
3 5 20
2 5 3
2 3 4
4 6 10
5 6 100

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了90 篇原创文章 · 获赞 31 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/BlackCarDriver/article/details/90243549