#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;
}