图的一系列操作

Graph.h
#pragma once
#include<iostream>
#include<vector>
#include<unordered_map>//哈希表

using namespace std;

class Graph
{
	vector<char>vertex;//定义点集
	vector<vector<int>>edges;//定义边集
	unordered_map<char, int>cityIndex;//城市所对应的下标
	vector<vector<int>>g;//二维数组存储图
public:
	void buildGraph(vector<char>& vertex,vector<vector<int>> &edges);
	void print();


};
Graph.cpp
#include "Graph.h"

void Graph::buildGraph(vector<char>& vertex, vector<vector<int>> &edges)
{
	this->vertex = vertex;
	this->edges = edges;
	for (int i = 0; i < vertex.size(); i++)
	{
		cityIndex[vertex[i]] = i;
	}
	int n = vertex.size();
	g.assign(n, vector<int>(n,0));//给二维数组赋值图先全部赋值为0
	for (int i = 0; i < edges.size(); i++)
	{	
			int gi = cityIndex[edges[i][0]];
			int gj = cityIndex[edges[i][1]];
			g[gi][gj] = edges[i][2];	
	}
}

void Graph::print()
{
	for (int i = 0; i < g.size(); i++)
	{
		for (int j = 0; j < g[i].size(); j++)
		{
			cout << g[i][j]<< " ";
		}
		cout << endl;
	}
}
main.cpp
#include"Graph.h"
#include<iostream>

using namespace std;


int main()
{
	vector<char>vertex={'A','B','C','D','E','F','G'};
	vector<vector<int>>edges=
	{
		{'A','B',5},
		{'A','C',2},
		{'B','A',5},
		{'B','D',1},
		{'B','E',6},
		{'C','D',6},
		{'C','F',8},
		{'C','A',2},
		{'D','B',1},
		{'D','C',6},
		{'D','E',1},
		{'D','F',2},
		{'E','B',6},
		{'E','D',1},
		{'E','G',7},
		{'F','C',8},
		{'F','D',2},
		{'F','G',3},
		{'G','E',7},
		{'G','F',3},
	};
	Graph G;
	G.buildGraph(vertex,edges);
	G.print();

	return 0;
}
图的广度优先遍历(BFS)
void Graph::BFS(char c)//广度优先遍历,用队列实现
{
	queue<char> que;
	que.push(c);
	unordered_set<char> mark;//标记已经入过队列的元素
	mark.insert(c);
	while (!que.empty())
	{
		char h=que.front();
		cout << h << " ";
		que.pop();
		int index = cityIndex[h];//从h城市出发,能到达哪些点,把没被标记过的点放入队列
		for (int i = 0; i < vertex.size(); i++)
		{ 
			char city = vertex[i];
				if (g[index][i] != 0 && mark.find(city) == mark.end())//g[index][i]从h城市出发能到达的点 ,这个城市没在mark里面
				{
					que.push(city);
					mark.insert(city);
	     	    }
		}
	}
}
图的深度优先遍历(DFS)
void Graph::DFS(char c)//深度优先遍历,用栈实现
{
	stack<char> stk;
	stk.push(c);
	unordered_set<char> mark;
	mark.insert(c);//标记已经入过栈的元素
	while (!stk.empty())
	{
		char h = stk.top();
		cout << h << " ";
		stk.pop();
		int index = cityIndex[h];//从h城市出发,能到达哪些点,把没被标记过的点放入栈
		for (int i = 0; i < vertex.size(); i++)
		{
			char city = vertex[i];
			if (g[index][i] != 0 && mark.find(city) == mark.end())//g[index][i]从h城市出发能到达的点 ,这个城市没在mark里面
			{
				stk.push(city);
				mark.insert(city);
			}
		}
	}
}
dijkstra
void Graph::dijkstra(char c)
{
	vector<int> res;
	unordered_set<char> mark;
	//初始化
	vector<char> pre(vertex.size(),c);
	res = g[cityIndex[c]];
	mark.insert(c);
	while (mark.size()<vertex.size())
	{
		//在res找最小值,刨除mark里面的
		int min = INT_MAX;
		int minIndex = -1;
		for(int i=0;i<res.size();i++)
		{
			//City[i]就是i所对应的城市,看看这个城市是否被标记
			if(min>res[i] && mark.find(vertex[i])==mark.end())
			{
				min = res[i];
				minIndex = i;
			}	
		}
		char m = vertex[minIndex];
		mark.insert(m);
		//看看哪些城市可以通过city[index]到达c,更新res和pre,刨除mark里面的
		//遍历 哪一行 minIndex
		for(int i=0;i<vertex.size();i++)
		{
			int tmp = g[minIndex][i] == INT_MAX ? INT_MAX : g[minIndex][i] + min;
			if(tmp<res[i]&&mark.find(vertex[i])==mark.end())
			{
				res[i] = tmp;
				pre[i] = m;
			}
		}
	}
	for (int i = 0; i < res.size();i++)
	{
		cout << res[i] << " ";
	}
	cout << endl;

	for (int i = 0; i < pre.size(); i++)
	{
		cout << pre[i] << " ";
	}
	cout << endl;
}
Prim(构建最小生成树)
void Graph::prim(char c)
{
	//标记哪些点没被选过
	unordered_set<char> mark;//存放未被选中的点
	vector<Node *>res;//存放结果
	priority_queue<Node *,vector<Node *>,cmp>minheap;//优先级队列
	for(auto city:vertex)//初始化mark
	{
		if (c != city)
		{
			mark.insert(city);
		}
	}
	//for(int i=0;i<vetex.size();i++)同上
	//{
	/*if (vertex[i] != c)
		mark.insert(vertex[i]);*/
	//}
	char pick = c;//被选择的点
	while (mark.size())
	{
		//从被选择点可以到达哪些点
		//被选择点得下标 cityIndex(pick)
		for(int i=0;i<vertex.size();i++)
		{
			int val = g[cityIndex[pick]][i];
			if (val != INT_MAX && mark.find(vertex[i]) != mark.end())
			{
				minheap.push(new Node(val,pick,vertex[i]));
			}		
		}
		//从最小堆里找最小值,终点也必须在mark里面
		while(1)
		{
			Node *top = minheap.top();
			minheap.pop();
			if(mark.find(top->end)!=mark.end())
			{
				res.push_back(top);
				pick = top->end;
				mark.erase(top->end);
				break;
			}
			delete top;
		}
	}

	for(int i=0;i<res.size();i++)
	{
		cout << res[i]->start << " " << res[i]->end << " " << res[i]->val<<endl;	
	}
}
并查集
struct Node
{
	char key;
	Node *father;
	Node(char k)
	{
		key = k;
		father = this;
	}

};

class UnionFind
{
	//key 一下子找到这个节点
	unordered_map<char, Node *>keyNode;
	//根节点(教主) 帮派人数
	unordered_map<Node *, int> nodesCount;

public:
	UnionFind(vector<char>pointSet);
	Node * findRoot(char t);//找到根节点(教主)
	bool isSameset(char t1,char t2);//是否属于一个帮派
	void UnionSets(char t1,char t2);//合并帮派
	void printNodes();

};

.cpp
#include "并查集.h"

//key 一下子找到这个节点
//unordered_map<char, Node *>keyNode;
//根节点(教主) 帮派人数
//unordered_map<Node *, int> nodesCount;

UnionFind::UnionFind(vector<char>pointSet)
{
	for (auto point : pointSet)
	{
		Node *node = new Node(point);
		keyNode[point] = node;
		nodesCount[node] = 1;
	}
}

Node * UnionFind::findRoot(char t)//找到根节点(教主)
{
	Node *node = keyNode[t];
	Node *father = node->father;
	stack<Node *>stk;
	//当node!=father,说明他不是教主,就得往上找
	while (node != father)
	{
		stk.push(node);
		node = father;
		father = node->father;
	}
	while (!stk.empty())
	{
		stk.top()->father=father;
		stk.pop();
	}

	return father;
}

bool UnionFind::isSameset(char t1, char t2)//是否属于一个帮派
{
	//t1或者t2不属于点集的时候
	if(keyNode.find(t1)==keyNode.end()|| keyNode.find(t2) == keyNode.end())
	{
		return false;
	}
	if(findRoot(t1)==findRoot(t2))
	{
		return true;
	}
	else return false;
	//简单写成 return findRoot(t1)==findRoot(t2);
}

void UnionFind::UnionSets(char t1, char t2)
{
	//t1或者t2不属于点集的时候
	if (keyNode.find(t1) == keyNode.end() || keyNode.find(t2) == keyNode.end())
	{
		return;
	}
	Node *root1 = findRoot(t1);
	Node *root2 = findRoot(t2);
	int numOfRoot1 = nodesCount[root1];
	int numOfRoot2 = nodesCount[root2];
	if (numOfRoot1 > numOfRoot2)
	{
		root2->father = root1;
		nodesCount[root1] = numOfRoot2 + numOfRoot1;
		nodesCount.erase(root2);
	}
	else
	{
		root1->father = root2;
		nodesCount[root2] = numOfRoot1 + numOfRoot2;
		nodesCount.erase(root1);	
	}
}

//根节点(教主) 帮派人数
//unordered_map<Node *, int> nodesCount;
void UnionFind::printNodes()
{
	for (auto it : nodesCount)
		cout << it.first->key <<" "<< it.second << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值