深度廣度優先遍歷最小生成樹
阿新 • • 發佈:2019-02-18
怎麼用圖的深度和廣度優先遍歷來遍歷樹呢?我是這樣想的,把樹構造成圖就行了。
廣度優先用到的佇列:// 圖的遍歷.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "LinkQueue.h" #include <stdio.h> #include <stdlib.h> #define VRType int//在這裡是權值型別 #define MAX_VERTEX_NUM 10//最大頂點個數 #define VertexType char //頂點型別 #define INFINITY 32767 //無窮大,不連通 //邊的結構 typedef struct ArcCell{ VRType adj;//權值 }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //圖的結構 typedef struct { VertexType vexs[MAX_VERTEX_NUM];//頂點向量 AdjMatrix arcs;//鄰接矩陣 int vexnum,arcnum;//頂點數,邊數 }MGraph; //輔助陣列,記錄從U到V-U的最小代價的邊 typedef struct { VertexType adjvex; VRType lowcost; }Closedge; ////////// typedef struct edge{ int begin;//起始頂點位置 int end;//終點位置 VRType weight;//權重 }Edge[100]; //函式宣告 void CreateMGraph(MGraph &G);//建立圖 void PrintGraph(MGraph G);//列印圖 void Prim(MGraph G,VertexType v,MGraph &TG);// void Kruskal(MGraph G,MGraph &TG); //找到結點v在圖G中的序號,返回,沒找到返回-1 int LocateVex(MGraph G,VertexType v); void InitGraph(MGraph &G,int arcnum,int vertexnum);//初始化圖 //把G圖中的一條邊新增到TG中去 void AddArc(MGraph &TG,MGraph G,VertexType v1,VertexType v2,VRType weight); //返回v結點的第一個鄰接頂點的序號,沒找到返回-1 int FirstAdjVex(MGraph G,VertexType v); //返回v相對於w的下一個鄰接點,若w是v的最後一個鄰接頂點,返回-1 int NextAdjVex(MGraph G,VertexType v,VertexType w); //遞迴深度優先遍歷圖 int visited[MAX_VERTEX_NUM] = {0};//訪問標記陣列 void DFSG(MGraph G,void (*Visit)(VertexType)); void DFS(MGraph G,int i); //非遞迴廣度優先遍歷圖 void BFSG(MGraph G,void(*Visit)(VertexType)); //對結點的操作函式 void (*VisitFunc)(VertexType v);//全域性變數,方便訪問VisitNode void VisitNode(VertexType v); int main(){ int i=1; MGraph G,TG; VertexType v; while(i){ InitGraph(TG,0,1); printf("第%d個圖:\n",i++); CreateMGraph(G); PrintGraph(G); //Prim演算法 printf("========Prim演算法========:\n輸入從哪個頂點開始構造:"); fflush(stdin); scanf("%c",&v); Prim(G,v,TG); PrintGraph(TG); /*--------------- for(int k=0;k<TG.vexnum;k++){ printf("%c-%d----",TG.vexs[k],LocateVex(TG,TG.vexs[k])); } printf("\n"); /*---------------*/ printf("========DFS=======\n"); DFSG(TG,VisitNode); printf("\n========BFS=======\n"); BFSG(TG,VisitNode); //Kruskal演算法 printf("\n========Kruskal演算法========:\n"); InitGraph(TG,0,1);//重新初始化TG Kruskal(G,TG); PrintGraph(TG); printf("========DFS=======\n"); DFSG(TG,VisitNode); printf("\n========BFS=======\n"); BFSG(TG,VisitNode); system("pause"); } return 0; } //函式實現 int minimum(Closedge *closedge,MGraph G){ int i=0,j,k,min; while(!closedge[i].lowcost){//找到第一個權值不為零的 i++; } min = closedge[i].lowcost; k = i; for(j=i+1;j<G.vexnum;j++){ if(closedge[j].lowcost >0 && min >closedge[j].lowcost){ min = closedge[j].lowcost; k = j; } } return k; } /*---------*/ void printCloseE(Closedge*close,int n){ for(int i=0;i<n;i++){ printf("closedge[%d].adjvex=%c || closedge[%d].lowcost=%d\n",i,close[i].adjvex,i,close[i].lowcost); } } /*---------*/ void Prim(MGraph G,VertexType v,MGraph &TG){ int k = LocateVex(G,v),i=0,j=0; Closedge closedge[MAX_VERTEX_NUM]; //輔助矩陣初始化 for(i=0;i<G.vexnum;i++){ closedge[i].adjvex = v; closedge[i].lowcost = G.arcs[k][i].adj; } closedge[k].lowcost = 0;//把結點v加入集合U中 /*-------- printCloseE(closedge,G.vexnum); /*--------*/ for(i=1;i<G.vexnum;i++){ k = minimum(closedge,G) ;//求出最小生成樹的下一個節點,第k頂點 printf("%c--->%c\n",closedge[k].adjvex,G.vexs[k]); AddArc(TG,G,closedge[k].adjvex,G.vexs[k],closedge[k].lowcost); closedge[k].lowcost = 0;//第k結點加入U //重新選擇最小邊 for(j=0;j<G.vexnum;j++){ if( G.arcs[k][j].adj < closedge[j].lowcost){ closedge[j].adjvex = G.vexs[k]; closedge[j].lowcost = G.arcs[k][j].adj; } } /*-------- printf("===============\n"); printCloseE(closedge,G.vexnum); /*--------*/ } } //列印邊陣列 void print(Edge *E,int n,MGraph G){ for(int i=0;i<n;i++){ printf("%c---%c---%d\n",G.vexs[E[i]->begin],G.vexs[E[i]->end],G.arcs[E[i]->begin][E[i]->end].adj); } } //按權值從小到大排序 int cmp(const void *a,const void *b){ return ((struct edge*)a)->weight - ((struct edge*)b)->weight; } void Kruskal(MGraph G,MGraph &TG){ Edge *E = (Edge*)malloc(sizeof(Edge)*G.arcnum*2) ; int i=0,j=0,k=0; for(i=0;i<G.vexnum;i++){ for(j=0;j<G.vexnum;j++){ if(G.arcs[i][j].adj != INFINITY){ E[k]->begin = i; E[k]->end = j; E[k]->weight = G.arcs[i][j].adj; k++; } } } qsort(E,k,sizeof(E[0]),cmp); print(E,k,G); int *vset = (int *)malloc(sizeof(int)*G.vexnum); for (i=0;i<G.vexnum;i++){ //初始化輔助陣列 vset[i]=i; } k=1; //生成的邊數,最後要剛好為總邊數 j=0; //E中的下標 while (k<G.vexnum){ int set1 = vset[E[j]->begin]; int set2 = vset[E[j]->end]; //得到兩頂點屬於的集合 /*---------- printf("set1 = %d||set2 = %d\n",set1,set2); /*----------*/ if (set1!=set2){ //不在同一集合內的話,把邊加入最小生成樹 printf("%c--->%c weight = %d\n",G.vexs[E[j]->begin],G.vexs[E[j]->end],E[j]->weight); //加進邊 AddArc(TG,G,G.vexs[E[j]->begin],G.vexs[E[j]->end],E[j]->weight); k++; for (i=0;i<G.vexnum;i++) { if (vset[i]==set2) { vset[i]=set1; } } /*---------- for(int c=0;c<G.vexnum;c++){ printf("vset[%d]=%d ",c,vset[c]); } printf("\n"); /*----------*/ } j++; } free(vset); free(E); } void CreateMGraph(MGraph &G){ printf("輸入頂點數,邊數:"); int vexnum=0,arcnum=0; scanf("%d %d",&vexnum,&arcnum); //初始化矩陣 InitGraph(G,arcnum,vexnum); int i=0,j=0; for(i=0;i<G.vexnum;i++){ printf("輸入第%d個頂點編號:",i+1); fflush(stdin); scanf("%c",&G.vexs[i]); } char v1,v2; int w; for(int k=0;k<G.arcnum;k++){ printf("輸入頂點1,頂點2及其權值:"); fflush(stdin); scanf("%c %c %d",&v1,&v2,&w); i = LocateVex(G,v1); j = LocateVex(G,v2); G.arcs[i][j].adj = w; G.arcs[j][i] = G.arcs[i][j];//對稱邊 } } int LocateVex(MGraph G,VertexType v){ for(int i=0;i<G.vexnum;i++){ if(v == G.vexs[i]){ return i; } } return -1; } //初始化一個圖 void InitGraph(MGraph &G,int arcnum,int vertexnum){ G.arcnum = arcnum; G.vexnum = vertexnum; for(int i=0;i<MAX_VERTEX_NUM;i++){ for(int j=0;j<MAX_VERTEX_NUM;j++){ G.arcs[i][j].adj = INFINITY; } } } //列印一個圖,二維 void PrintGraph(MGraph G){ printf("\n"); for(int i=0;i<G.vexnum;i++){ for(int j=0;j<G.vexnum;j++){ printf("%10d",G.arcs[i][j].adj); /*----------- printf("%d",G.arcs[i][j].adj); if(G.arcs[i][j].adj!=INFINITY){ printf("(%c-%d)",G.vexs[i],i); } printf("\t"); /*-------------*/ } printf("\n"); } } //向TG圖中加一條邊 void AddArc(MGraph &TG,MGraph G,VertexType v1,VertexType v2,VRType weight){ int i = LocateVex(G,v1); int j = LocateVex(G,v2); TG.vexs[i] = v1; TG.vexs[j] = v2; /*------------ printf("%c-%d\n%c-%d",G.vexs[i],i,G.vexs[j],j); /*------------*/ if(i>=0 && j>=0){ TG.arcs[i][j].adj = weight; TG.arcs[j][i].adj = weight; TG.arcnum++; TG.vexnum++; } } //////////////// int FirstAdjVex(MGraph G,VertexType v){ int k = LocateVex(G,v); for(int i=0;i<G.vexnum;i++){ if(G.arcs[k][i].adj != INFINITY){//第一個權值不為無窮大的點就是 return i; } } return -1; } /////////////////// int NextAdjVex(MGraph G,VertexType v,VertexType w){ int a = LocateVex(G,v); int b = LocateVex(G,w); for(int i=b+1;i<G.vexnum;i++){ if(G.arcs[a][i].adj != INFINITY){ return i; } } return -1; } ///////////////////// void DFSG(MGraph G,void (*Visit)(VertexType)){ int i=0; VisitFunc = Visit; for(i=0;i<G.vexnum;i++){ visited[i] = 0;//初始化,0代表沒訪問 } for(i=0;i<G.vexnum;i++){ if(!visited[i]){//第i個結點沒被訪問,就遞迴搜尋 DFS(G,i); } } } void DFS(MGraph G,int i){ //從第i個結點出發深度優先遍歷圖 visited[i] = 1; VisitFunc(G.vexs[i]); for(int j = FirstAdjVex(G,G.vexs[i]);j>=0;j = NextAdjVex(G,G.vexs[i],G.vexs[j])){ if(!visited[j]){ DFS(G,j); } } } ///////////////// void BFSG(MGraph G,void(*Visit)(VertexType)){ int i=0,k=0; for(i=0;i<G.vexnum;i++){ visited[i] = 0; } VertexType u; LinkQueue Q; InitQueue(Q); for(i=0;i<G.vexnum;i++){ if(!visited[i]){ visited[i] = 1; Visit(G.vexs[i]); EnQueue(Q,G.vexs[i]); while(!QueueEmpty(Q)){ DeQueue(Q,u); for(k=FirstAdjVex(G,u);k>=0;k=NextAdjVex(G,u,G.vexs[k])){ if(!visited[k]){ visited[k] = 1; Visit(G.vexs[k]); EnQueue(Q,G.vexs[k]); } } } } } } ////////////////// void VisitNode(VertexType v){ printf("結點%c----->",v); }
#include <stdio.h> #include <stdlib.h> #define QElemType char typedef struct QNode{ QElemType data; QNode *next; }*QueuePtr; struct LinkQueue{ QueuePtr front,rear; }; void InitQueue(LinkQueue &Q){ if(!(Q.front=Q.rear = (QueuePtr)malloc(sizeof(QNode)))){ exit(-1);//溢位 } Q.front->next = NULL; } void EnQueue(LinkQueue &Q,QElemType e){ QueuePtr p; if(!(p = (QueuePtr)malloc(sizeof(QNode)))){ exit(-1); } p->data = e; p->next = NULL; Q.rear->next = p; Q.rear = p; } int DeQueue(LinkQueue &Q,QElemType &e){ QueuePtr p; if(Q.front==Q.rear){ return -1; } p = Q.front->next; e = p->data; Q.front->next = p->next; if(Q.rear==p){ Q.rear = Q.front; } free(p); return 1; } int QueueEmpty(LinkQueue Q){ if(Q.front==Q.rear){ return 1; }else{ return 0; } }
執行結果:
輸出的排版變了一下,別忘了。。。