C++之图

#include<iostream>
#include<queue>
#include<stack>
using namespace std;
template <class T>
class minheap{  // 最小堆类定义    初始化,插入,删除堆顶元素	
private:
	T * heaparray;
	int currentsize;
	int maxsize;
public:
	minheap(int n){
		if(n<=0)
			return;
		currentsize=0;
		maxsize=n;
		heaparray=new T[maxsize];
		buildheap();
	}
	~minheap(){
		delete [] heaparray;
	}
	void buildheap(){
		for(int i=currentsize/2-1;i>=0;i--)
			siftdown(i);//反复调用筛选函数
	}
	void siftdown(int left){//筛选法函数,参数left表示开始处理的数组下标
		int i=left;
		int j=2*i+1;
		T temp=heaparray[i];
		while(j<currentsize){
			if((j<currentsize-1)&&(heaparray[j]>heaparray[j+1]))
				j++;
			if(temp>heaparray[j]){
				heaparray[i]=heaparray[j];
			    i=j;
				j=2*j+1;
			}
			else break;
		}2
		heaparray[i]=temp;
	}
	void siftup(int pos){//从pos向上开始调整
		int temppos=pos;
		T temp=heaparray[temppos];
		while((temppos>0)&&(heaparray[(temppos-1)/2]>temp))
		{
			heaparray[temppos]=heaparray[(temppos-1)/2];
			temppos=(temppos-1)/2;
		}
		heaparray[temppos]=temp;
	}
	void insert(const T & newnode){//向堆中插入新元素newnode
		heaparray[currentsize]=newnode;
		siftup(currentsize);
		currentsize++;
	}
	T & removemin(){//从堆顶删除最小值
		T temp;
		if(currentsize==0){
			cout<<"can't delete";
			exit(1);
		}
		else{
			temp=heaparray[0];
			heaparray[0]=heaparray[currentsize-1];
			heaparray[currentsize-1]=temp;
			currentsize--;
			if(currentsize>0)
				siftdown(0);
			return heaparray[currentsize];
		}
	}
	bool isempty(){
		if(currentsize==0)
			return true;
		else
			return false;
	}
};
template <class T>
class maxheap{  // 最大堆类定义    初始化,插入,删除堆顶元素
private:
	T * heaparray;
	int currentsize;
	int maxsize;
public:
	maxheap(int n){
		if(n<=0)
			return;
		currentsize=0;
		maxsize=n;
		heaparray=new T[maxsize];
		buildheap();
	}
	~maxheap(){
		delete [] heaparray;
	}
	void buildheap(){
		for(int i=currentsize/2-1;i>=0;i--)
			siftdown(i);//反复调用筛选函数
	}
	void siftdown(int left){//筛选法函数,参数left表示开始处理的数组下标
		int i=left;
		int j=2*i+1;
		T temp=heaparray[i];
		while(j<currentsize){
			if((j<currentsize-1)&&(heaparray[j]<heaparray[j+1]))
				j++;
			if(temp<heaparray[j]){
				heaparray[i]=heaparray[j];
			    i=j;
				//heaparray[i]=temp;
				j=2*j+1;
			}
			else break;
		}
		heaparray[i]=temp;
	}
	void siftup(int pos){//从pos向上开始调整
		int temppos=pos;
		T temp=heaparray[temppos];
		while((temppos>0)&&(heaparray[(temppos-1)/2]<temp)){
			heaparray[temppos]=heaparray[(temppos-1)/2];
			temppos=(temppos-1)/2;
		}
		heaparray[temppos]=temp;
	}
	void insert(const T & newnode){//向堆中插入新元素newnode
		heaparray[currentsize]=newnode;
		siftup(currentsize);
		currentsize++;
		
	}
 	T & removemax(){//从堆顶删除最大值
		T temp;
		if(currentsize==0){
			cout<<"can't delete";
			exit(1);
		}
		else{
			temp=heaparray[0];
			heaparray[0]=heaparray[currentsize-1];
			heaparray[currentsize-1]=temp;
			currentsize--;
			if(currentsize>0)
				siftdown(0);
			return heaparray[currentsize];
		}
	}
	void display(){//输出树中元素
		for(int i=0;i<currentsize;i++)
			cout<<heaparray[i]<<" ";
		cout<<endl;
	}
	bool isempty(){
		if(currentsize==0)
			return true;
		else
			return false;
	}
};
template <class T>
class Edge{//边类型
public:
	int start,end;
	T weight;
	Edge(){
		start=0;
		end=0;
	}
	Edge(int st,int en,T w){
		start=st;
		end=en;
		weight=w;
	}
	bool operator > (Edge oneEdge){
		return weight>oneEdge.weight;
	}
	bool operator < (Edge oneEdge){
		return weight<oneEdge.weight;
	}
};
class ufsets{//等价类定义
private:
	int * root;//元素i所在等价类中根元素编号
	int * next;//i后面元素编号
	int * length;//i等价类中元素个数
public:
	ufsets(int size){//初始化size个元素的等价类
		int n=size;
		root=new int[n];
		next=new int[n];
		length=new int[n];
		for(int i=0;i<n;i++){
			root[i]=i;
			next[i]=i;
			length[i]=1;
		}
	}
	int find(int v){//查找根结点
		return root[v];
	}
	void swap(int & i,int & j){
		int temp;
		temp=i;
		i=j;
		j=temp;
	}
	void Union(int v,int u){//合并u和v所在等价类
		int rt,j;
		if(root[v]==root[u])//如果在一个等价类中则返回
			return;
		else if(length[root[v]]<length[root[u]]){//v合并到u
			rt=root[v];
			length[root[u]]+=length[rt];
			root[rt]=root[u];
			for(j=next[rt];j!=rt;j=next[j])
				root[j]=root[u];
			swap(next[rt],next[root[u]]);//交换后继结点,连接两个等价类
		}
		else{
			rt=root[u];
			length[root[v]]+=length[rt];
			root[rt]=root[v];
			for(j=next[rt];j!=rt;j=next[j])
				root[j]=root[v];
			swap(next[rt],next[root[v]]);
		}
	}
};
template <class T>
class Graph{//图类型
public:
	int vertexNum;//图的顶点数目
	int edgeNum;//图的边数目
	int * Mark;//标记某顶点是否被访问过,访问过为1,没访问为0
	Graph(int ver){
		vertexNum=ver;
		edgeNum=0;
		Mark=new int[ver];
		for(int i=0;i<ver;i++){
			Mark[i]=0;
		}
	}
	~Graph(){
		delete [] Mark;
	}
	virtual Edge<T> FirstEdge(int onevertex)=0;//返回与顶点相关联的第一条边
	virtual Edge<T> NextEdge(Edge<T> oneEdge)=0;//返回与oneedge有相同起点的下一条边
	int verticesnum(){//返回顶点个数
		return vertexNum;
	}
	int edgesnum(){//返回边个数
		return edgeNum;
	}
	bool isedge(Edge<T> oneEdge){//判断是否为边
		if(oneEdge.weight>0&&oneEdge.weight<100)
			return true;
		else
			return false;
	}
	int startvertex(Edge<T> oneEdge){//返回边的始点
		return oneEdge.start;
	}
	int endvertex(Edge<T> oneEdge){//返回边的终点
		return oneEdge.end;
	}
	T Weight(Edge<T> oneEdge){//返回边的权重
		return oneEdge.weight;
	}
	virtual void setEdge(int start,int end,T weight)=0;//设置边
	virtual void delEdge(int start,int end)=0;//删除边
	void visit(int v){//访问结点
		cout<<v<<' ';
	}
	void DFS(int v){//从某顶点开始递归深度优先搜索
		visit(v);
		Mark[v]=1;	
		for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
			if(Mark[endvertex(e)]==0)
				DFS(endvertex(e));
		}
	}
	void DFS1(int v){//从某顶点开始递归深度优先搜索
		Mark[v]=1;	
		for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
			if(Mark[endvertex(e)]==0)
				DFS1(endvertex(e));
		}
	}
	void DFStraverse(){//图的递归深度优先搜索
		int i;
		for(i=0;i<vertexNum;i++)
			Mark[i]=0;
		for(i=0;i<vertexNum;i++){
			if(Mark[i]==0)
				DFS(i);
		}
	}
	void DFSNoReverse(){//非递归法深度优先遍历
		int i,v,u;
		ArrayStack<int> s;
		for(i=0;i<vertexNum;i++)
			Mark[i]=0;
		for(i=0;i<vertexNum;i++){
			if(Mark[i]==0){
				s.push(i);
				visit(i);
				Mark[i]=1;
				while(!s.isEmpty()){
					v=s.pop();
					for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
						i=endvertex(e);
						if(Mark[i]==0){
							s.push(i);
							visit(i);
							Mark[i]=1;
						}
					}
				}
			}
		}
	}
	void BFS(int v){//从某结点开始广度优先搜索
		queue<int> Q;
		Mark[v]=1;
		visit(v);
		Q.push(v);
		while(!Q.empty()){
			v=Q.front();
		    Q.pop();
			for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
				int u=Mark[endvertex(e)];
				int m=endvertex(e);
				if(u==0){
					visit(m);
					Mark[m]=1;
					Q.push(m);
				}
			}
		}
	}
	void BFStraverse(){//图的广度优先搜索
		int v;
		for(v=0;v<vertexNum;v++)
			Mark[v]=0;
		for(v=0;v<vertexNum;v++){
			if(Mark[v]==0)
				BFS(v);
		}
	}	
};
template <class T>
class AdjGraph:public Graph<T>{//图的邻接矩阵表示
private:
	int ** matrix;
public:
	AdjGraph(int ver):Graph(ver){
		int i,j;
		matrix=(int **)new int *[ver];
		for(i=0;i<ver;i++)
			matrix[i]=new int[ver];
		for(i=0;i<ver;i++)
			for(j=0;j<ver;j++)
				matrix[i][j]=100;//存权重
	}
	~AdjGraph(){
		for(int i=0;i<vertexNum;i++)
			delete []matrix[i];
		delete []matrix;
	}
	Edge<T> FirstEdge(int onevertex){//返回与顶点相关联的第一条边
		Edge<T> tmpEdge;
		tmpEdge.start=onevertex;
		for(int i=0;i<vertexNum;i++){
			if(matrix[onevertex][i]!=100){
				tmpEdge.end=i;
				tmpEdge.weight=matrix[onevertex][i];
				break;
			}
		}
		return tmpEdge;
	}
	Edge<T> NextEdge(Edge<T> oneEdge){//返回与oneEdge有相同起点的下一条边
		Edge<T> tmpEdge;
		tmpEdge.start=oneEdge.start;
		for(int i=oneEdge.end+1;i<vertexNum;i++){
			if(matrix[oneEdge.start][i]!=100){
				tmpEdge.end=i;
				tmpEdge.weight=matrix[oneEdge.start][i];
				break;
			}
		}
		return tmpEdge;
	}
	void setEdge(int start,int end,T weight){//为图新增一条边
		if(matrix[start][end]==100)
			edgeNum++;
		matrix[start][end]=weight;
	}
	void delEdge(int start,int end){//删除一条边
		if(matrix[start][end]!=100)
			edgeNum--;
		matrix[start][end]=100;
	}
	void Prim(int s){//应用Prim算法从s顶点出发得到的最小生成树
		int i,j;
		int n=vertexNum;
		Edge<T> * MST=new Edge<T>[n-1];
		T * nearest=new T[n];
		int * neighbor=new int[n];
		for(i=0;i<n;i++){
			neighbor[i]=s;//表示生成树中与i点最近的点的编号
			nearest[i]=100;//生成树中到i点的最小边权值
		}
		for(Edge<T> e=FirstEdge(s);isedge(e);e=NextEdge(e)){
			nearest[e.end]=e.weight;
		}
		neighbor[s]=-1;
		for(i=0;i<n;i++){//i标记已经加入树中的点的个数
			T min=100;
			int v=-1;
			for(j=0;j<n;j++){
				if(nearest[j]<min&&neighbor[j]>-1){
					min=nearest[j];
					v=j;
				}
			}
			if(v>=0){
				Edge<T> tempEdge(neighbor[v],v,nearest[v]);
				neighbor[v]=-1;
				MST[i]=tempEdge;
				for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
					int u=e.end;
					if(neighbor[u]!=-1&&nearest[u]>e.weight){
						neighbor[u]=v;
						nearest[u]=e.weight;
					}
				}
			}
		}
		for(i=0;i<n-1;i++)
			cout<<MST[i].start<<MST[i].end<<' ';
		cout<<endl;
	}
	void kruskal(){//克鲁斯卡尔算法计算最小生成树
		int n=vertexNum;
		ufsets set(n);
		Edge<T> * MS=new Edge<T>[n-1];
		minheap<Edge<T>> H(edgeNum);
		Edge<T> edge;
		for(int i=0;i<vertexNum;i++){
			for(edge=FirstEdge(i);isedge(edge);edge=NextEdge(edge)){
				if(startvertex(edge)<endvertex(edge))
					H.insert(edge);
			}
		}
		int edgenu=0;
		while(edgenu<n-1){
			if(!H.isempty()){
				edge=H.removemin();
				int v=edge.start;
				int u=edge.end;
				if(set.find(v)!=set.find(u)){
					set.Union(v,u);
					MS[edgenu++]=edge;
				}
			}
		}
		for(int m=0;m<edgenu;m++)
			cout<<MS[m].start<<MS[m].end<<MS[m].weight<<' ';
		cout<<endl;
	}
	void dijkstra(int s){//迪杰特斯拉最短路径
		int n=vertexNum;
		T * D=new T[n];
		int * Path=new int[n];//D为权值,Path为前驱
		int i,j;
		for(i=0;i<n;i++){
			Mark[i]=0;
            D[i]=100;
            Path[i]=-1;//标记此时不存在s到i的路径
		}
		Mark[s]=1;
		D[s]=0;
		Path[s]=s;
		for(i=0;i<n;i++){//找到一条最短特殊路径
			T min=100;
			int k=0;
			for(j=1;j<n;j++){
				if(Mark[j]==0&&min>D[j]){
					min=D[j];
					k=j;
				}
			}//已确定s到k的最短路径
			Mark[k]=1;//利用k更新到其余未访问路径的最短路径
			for(Edge<T> e=FirstEdge(k);isedge(e);e=NextEdge(e)){
				int endv=e.end;
				if(Mark[endv]==0&&D[endv]>(D[k]+e.weight)){
					D[endv]=D[k]+e.weight;//更新到endv的最短特殊路径
					Path[endv]=k;
				}
			}
		}
		for(i=0;i<n;i++)
			cout<<D[i]<<' ';
		cout<<endl;
	}
	void floyd(){//弗洛伊德最短路径
		int i,j,v;
		int n=vertexNum;
		T ** adj=(T **)new T *[n];
		for(i=0;i<n;i++)
			adj[i]=new T[n];
		int ** path=(int **)new int *[n];
		for(i=0;i<n;i++)
			path[i]=new int[n];
		for(i=0;i<n;i++){
			for(j=0;j<n;j++){
				if(i==j){
					adj[i][j]=0;
					path[i][j]=i;
				}
				else{
					adj[i][j]=100;
					path[i][j]=-1;
				}
			}
		}
		for(v=0;v<n;v++){
			for(Edge<T> e=FirstEdge(v);isedge(e);e=NextEdge(e)){
				adj[v][e.end]=e.weight;
				path[v][e.end]=v;
			}
		}
		for(v=0;v<n;v++)
			for(i=0;i<n;i++)
				for(j=0;j<n;j++){
					if(adj[i][j]>adj[i][v]+adj[v][j]){
						adj[i][j]=adj[i][v]+adj[v][j];
						path[i][j]=v;
					}
				}
				cout<<"Floyd算法输出:"<<endl;
				for(i=0;i<n;i++)
					for(j=0;j<n;j++)
						cout<<adj[i][j]<<' ';
				cout<<endl;
				for(i=0;i<n;i++)
					for(j=0;j<n;j++)
						cout<<path[i][j]<<' ';
				cout<<endl;
				
	}
	bool Toplogysort(int * sortarray){//拓扑排序,sortarray存储拓扑序列
		int n=vertexNum;
		int * indegree=new int[n];
		int v,i;
		Edge<T> e;
		for(v=0;v<n;v++){
			indegree[v]=0;
			Mark[v]=0;
		}
		for(v=0;v<n;v++)//统计各顶点入边信息
			for(e=FirstEdge(v);isedge(e);e=NextEdge(e))
				indegree[e.end]++;
		for(i=0;i<n;i++){//找到入度为0且未被访问过的顶点
			for(v=0;v<n;v++){
				if(indegree[v]==0&&Mark[v]==0)
					break;
			}
			if(v==n){
				//找不到入度为0的结点
				return false;//有回路
			}
			Mark[v]=1;
			sortarray[i]=v;
			for(e=FirstEdge(v);isedge(e);e=NextEdge(e))
				indegree[e.end]--;
		}
		return true;//无回路
	}
	void Toplogysortdisplay(){//用拓扑排序找自圈
		int n=vertexNum;
		int i;
		int * sortarray=new int[n];
		Edge<T> e;
		if(Toplogysort(sortarray)){
			
			   cout<<"无回路,拓扑序列为:";
			   for(int j=0;j<n;j++)
				  cout<<sortarray[j];
			   cout<<endl;
		}
		else{
			cout<<"存在回路,输出为:";
			for(i=0;i<n;i++)
			  for(e=FirstEdge(i);isedge(e);e=NextEdge(e))
				  if(Mark[e.end]==0)
					  break;
			cout<<e.end;
			Mark[e.end]=1;
			for(e=FirstEdge(e.end);isedge(e)&&Mark[e.end]==0;e=FirstEdge(e.end)){
				cout<<e.end;
				Mark[e.end]=1;
			}
			cout<<endl;
		}
	}
	void poquan(){//破圈法找最小生成树
		int n=vertexNum;
		int v;
		Edge<T> e;
		maxheap<Edge<T>> H(edgeNum);
		for(v=0;v<n;v++){
			for(e=FirstEdge(v);isedge(e);e=NextEdge(e)){
				if(e.start<e.end){
					H.insert(e);
				}
			}
		}
		while(!H.isempty()){
			e=H.removemax();
			int weight1=matrix[e.start][e.end];
			int weight2=matrix[e.end][e.start];
			matrix[e.start][e.end]=100;
			matrix[e.end][e.start]=100;
			if(!liantong()){  //若联通,则去掉最大边,不连通,不去除最大边
				  //或者判断从一个结点开始遍历,如果遍历过程中还会回到已经访问过的结点,则证明存在环,然后去除环中最大边
				matrix[e.start][e.end]=weight1;
				matrix[e.end][e.start]=weight2;
			}
		}
		cout<<"破圈法找到的最小生成树为:";
		for(v=0;v<n;v++){
			for(e=FirstEdge(v);isedge(e);e=NextEdge(e)){
				if(e.start<e.end){
					cout<<e.start<<e.end<<' ';
				}
			}
		}
		cout<<endl;
	}
	bool liantong( ){ //判断是否连通
		int count=0;
		for(int v=0;v<vertexNum;++v) 
			Mark[v]=0; //初始化未被访问 
		for(int v=0;v<vertexNum;++v)  {   
			if(!Mark[v]){      
				DFS1(v); 
				count++;    
			}  
		} 
		if(count==1)//连通
			return true;
		else//含多个连通分支,则不连通
			return false;
	}
};
int main(int argc, char* argv[])
{
	/*AdjGraph <int> tu(8);
	tu.setEdge(0,1,1);
	tu.setEdge(0,2,1);
	tu.setEdge(1,0,1);
	tu.setEdge(1,3,1);
	tu.setEdge(1,4,1);
	tu.setEdge(2,0,1);
	tu.setEdge(2,5,1);
	tu.setEdge(2,6,1);
	tu.setEdge(3,1,1);
	tu.setEdge(3,7,1);
	tu.setEdge(4,1,1);
	tu.setEdge(4,7,1);
	tu.setEdge(5,2,1);
	tu.setEdge(5,6,1);
	tu.setEdge(6,2,1);
	tu.setEdge(6,5,1);
	tu.setEdge(7,3,1);
	tu.setEdge(7,4,1);
	cout<<"深度优先遍历输出:";
	tu.DFStraverse();
	cout<<endl<<"广度优先遍历输出:";
	tu.BFStraverse();
	cout<<endl;*/
	AdjGraph <int> tu2(6);
	tu2.setEdge(0,1,6);
	tu2.setEdge(0,2,1);
	tu2.setEdge(0,3,5);
	tu2.setEdge(1,0,6);
	tu2.setEdge(1,2,5);
	tu2.setEdge(1,4,3);
	tu2.setEdge(2,0,1);
	tu2.setEdge(2,1,5);
	tu2.setEdge(2,3,5);
	tu2.setEdge(2,4,6);
	tu2.setEdge(2,5,4);
	tu2.setEdge(3,0,5);
	tu2.setEdge(3,2,5);
	tu2.setEdge(3,5,2);
	tu2.setEdge(4,1,3);
	tu2.setEdge(4,2,6);
	tu2.setEdge(4,5,6);
	tu2.setEdge(5,2,4);
	tu2.setEdge(5,3,2);
	tu2.setEdge(5,4,6);
	/*cout<<"Prim最小生成树:";
	tu2.Prim(0);
	cout<<"克鲁斯卡尔算法输出:";
	tu2.kruskal();
	cout<<"迪杰特斯拉最短路径:";
	tu2.dijkstra(0);
	AdjGraph <int> tu3(3);
	tu3.setEdge(0,1,10);
    tu3.setEdge(0,2,5);
	tu3.setEdge(1,0,9);
	tu3.setEdge(1,2,6);
	tu3.setEdge(2,0,2);
	tu3.setEdge(2,1,13);
	tu3.floyd();*/
	AdjGraph <int> tu4(4);
	tu4.setEdge(0,1,1);
    tu4.setEdge(0,2,1);
	tu4.setEdge(1,3,1);
	tu4.setEdge(2,1,1);
	tu4.setEdge(3,2,1);
	tu4.Toplogysortdisplay();
	tu2.poquan();
	system("pause");
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值