图的Kruskal算法

#include <iostream>
#include <vector>
#include <queue>

#define MaxSize 10
#define eletype int 
using namespace std;

bool visited[MaxSize][MaxSize]; //全局数组,记录结点是否已补访问

typedef struct edgenode {  //边表结点
	int adjvex;  //邻接点
	int weight;  //权值
	edgenode *next; //下一条边
};

typedef struct vertexnode { //顶点结点
	eletype data;  //结点数据
	edgenode *fist;  //指向第一条边
}AdjList[MaxSize];

typedef struct AdjListGraph {
	AdjList adjlist;  //邻接表
	int vex;  //顶点数
	int edge; //边数
};

typedef struct CSNode {
	int begin;  //起点
	int end;    //终点
	int weight; //权值
};


void Init() {  //初始化为未访问
	for (int i = 0; i < MaxSize; i++) {
		for (int j = 0; j < MaxSize; j++) {
			visited[i][j] = false;
		}
	}
}

int Location(AdjListGraph &G, eletype c) {  //寻找顶点数据的邻接点
	for (int i = 0; i < G.vex; i++) {
		if (G.adjlist[i].data == c) {
			return i;
		}
	}
	return -1;
}

void Create(AdjListGraph &G) {  //创建图
	cout << "请输入该图的顶点数以及边数:" << endl;
	cin >> G.vex >> G.edge;
	cout << "请输入相关顶点:" << endl;
	for (int i = 0; i < G.vex; i++) {
		cin >> G.adjlist[i].data;
		G.adjlist[i].fist = NULL;
	}
	eletype a, b;
	int c;
	int m, n;
	cout << "请输入相关边的顶点以及权值:" << endl;
	for (int i = 0; i < G.edge; i++) {
		cin >> a >> b>>c;
		m = Location(G, a);  //寻找顶点号
		n = Location(G, b);

		if (m != -1 && n != -1) {  //寻找到位置
			edgenode *temp = new edgenode;
			temp->adjvex = n;
			temp->weight = c;
			temp->next = G.adjlist[m].fist;
			G.adjlist[m].fist = temp;
		}
	}
}


//快速排序部分

void swap(CSNode * a, CSNode * b) {
	CSNode  tmp = *a;
	*a = *b;
	*b = tmp;
}

int partition(vector<CSNode> &array_list, int left, int right) {
	int index = left;
	int pivot = array_list[right].weight;
	for (int i = left; i< right; i++) {
		if (array_list[i].weight < pivot) {
			swap(&array_list[index], &array_list[i]);
			index++;
		}
	}
	swap(&array_list[right], &array_list[index]);
	return index;
}

void quick_sort(vector<CSNode> &array_list, int left, int right) {
	if (left >= right){
		return;
	}
	int index = partition(array_list, left, right);
	quick_sort(array_list, left, index - 1);
	quick_sort(array_list, index + 1, right);
}

int NotEmpty(vector<int> *vect) { //寻找第一个空的序号
	for (int i = 0; i < MaxSize; i++) {
		if (vect[i].size() == 0) {
			return i;
		}
	}
	return -1;
}

int Where_Locate(vector<int> *vect, int v) { //判断该序号在vect中的位置
	for (int i = 0; i < MaxSize; i++) {
		vector<int>::iterator iter;
		for (iter = vect[i].begin(); iter != vect[i].end(); iter++) {
			if (*iter == v) {
				return i;
			}
		}
	}
	return -1;
}

int Number_of_Statistical(vector<int> *vect,int &P) {  //统计顶点个数
	int sum = 0;
	P=0;
	for (int i = 0; i < MaxSize; i++) {
		sum += vect[i].size();
		if (vect[i].size() != 0) {
			P++;
		}
	}
	return sum;
}

void Copy(vector<int> *vect, vector<int> *vect_temp) { //复制
	for (int j = 0; j < MaxSize; j++) {
		vect_temp[j].assign(vect[j].begin(), vect[j].end());
	}
}

void Kruskal(AdjListGraph &G) {
	vector<CSNode> vec;
	for (int i = 0; i < G.vex; i++) {
		edgenode *temp = G.adjlist[i].fist;
		if (temp != NULL) {
			if (visited[i][temp->adjvex] == false) {
				CSNode p;
				p.begin = i; p.end = temp->adjvex;
				p.weight = temp->weight;
				vec.push_back(p);
				visited[i][temp->adjvex] = true;
				visited[temp->adjvex][i] = true;
			}
			while (temp->next != NULL) {
				temp = temp->next;
				if (visited[i][temp->adjvex] == false) {
					CSNode p;
					p.begin = i; p.end = temp->adjvex;
					p.weight = temp->weight;
					vec.push_back(p);
					visited[i][temp->adjvex] = true;
					visited[temp->adjvex][i] = true;
				}
			}
		}
	}  //将边信息存储在vec中
	quick_sort(vec,0,vec.size()-1);  //将边信息进行排序
	vector<int> vect[MaxSize]; //存储连通分量部分
	vector<int> vect_temp[MaxSize];  //保存修改之前的
	int P = 0,M=0,E=0;  //表示连通分量的个数
	for (int i = 0; i < vec.size(); i++) {
		Copy(vect, vect_temp);
		int first = Where_Locate(vect, vec[i].begin);
		int second= Where_Locate(vect, vec[i].end);
		//cout << first << " " << second << endl;
		if (first == -1 && second == -1) { //均不存在
			int location = NotEmpty(vect);
			vect[location].push_back(vec[i].begin);  //存储进vect[location]
			vect[location].push_back(vec[i].end);
		}
		else {
			if (first == -1 && second != -1) { //起点不存在,终点存在
				vect[second].push_back(vec[i].end);
			}
			else {
				if (first != -1 && second == -1) { //起点存在,终点不存在
					vect[first].push_back(vec[i].begin);
				}
				else {
					if (first != -1 && second != -1) { //起点存在,终点存在
						if (first != second) { //位于不同的连通分量中
							int min = first > second ? second : first;
							int max	= first < second ? second : first;
							vect[min].insert(vect[min].end(), vect[max].begin(), vect[max].end());//将vect[max]压入  
							vect[max].clear();  //清空
						}
						
					}
				}
			}
		}
		M = Number_of_Statistical(vect,P);
		E = E + 1;
		//cout << E << " " << P << " " << M << endl;
		if (E + P > M) { //存在环
			Copy(vect_temp, vect); //恢复原状
			E = E - 1;
		}
		else {
			cout << G.adjlist[vec[i].begin].data << " " << G.adjlist[vec[i].end].data << endl;
			//输出选边
		}
	}
}


int main() {
	AdjListGraph G;
	Init();
	Create(G);  //创建图
	Kruskal(G);
	system("pause");
	return 0;
}

/*
6 20
1 2 3 4 5 6
1 2 6
1 4 5
1 3 1
2 3 5
3 4 5
2 5 3
5 6 6
4 6 2
3 6 4
3 5 6
2 1 6
4 1 5
3 1 1
3 2 5
4 3 5
5 2 3
6 5 6
6 4 2
6 3 4
5 3 6

*/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值