遍历输入图的遍历
PS:今天上午,非常郁悶,有很多簡單基礎的問題搞得我有些迷茫,哎,代碼幾天不寫就忘。目前又不當COO,還是得用心記代碼哦!
????
概述
??? 遍歷分為深度優先遍歷和廣度優先遍歷,其對有向圖和無向圖都實用。深度優先,望文生義,就是只要存在后續節點就始終往下走,直到沒有后續節點或者后續節點已經被訪問輸出了;廣度優先,就是節點一層一層的輸出。舉個例子,
????
?
??? 下面的兩個圖,深度優先遍歷的結果為ABCD;而廣度優先遍歷的結果為ABDC。
??? 如何存儲下面的圖結構呢?可以采用數組表現法和鄰接法。我這里只介紹數組表現法。
??? 圖的結構體定義如下:
???
typedef struct {VertexType vexs[MAX_VERTEX_NUM]; //頂點向量VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//鄰接矩陣int vexnum,arcnum; //頂點數和弧數GKind kind; //圖的種類標識 }MGraph;????
??? 要對圖停止遍歷,首先應當把圖建立起來。以建立無向圖為例。
??? 輸入:定點數、邊數、定點標號、邊的長度。
??? 詳細的創立代碼如下:
//創立無向圖 void CreatUDG(MGraph &G) {int i,j,k,w;char v1,v2;printf("輸入頂點數和邊數:");scanf("%d%d",&G.vexnum,&G.arcnum); visited = (int *)malloc(G.vexnum*sizeof(int));for ( i = 0; i < G.vexnum; i++ )visited[i] = 0;printf("請按次序輸入%d個頂點字母標號(如ABC等):",G.vexnum);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; i++ )scanf("%c",&G.vexs[i]);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; ++i )for ( j = 0; j < G.vexnum; ++j ){//初始化鄰接矩陣if ( i == j )G.arcs[i][j] = 0;elseG.arcs[i][j] = INT_MAX;}printf("輸入邊的頂點和權值(如A B 1):\n");for ( k = 0; k < G.arcnum; k++ ){scanf("%c %c %d",&v1,&v2,&w);i = LocateVex(G,v1);j = LocateVex(G,v2);G.arcs[i][j] = w;G.arcs[j][i] = w;getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵} }????
??? 源代碼
??? 以下是遍歷的完全代碼:
每日一道理聰明人學習,像搏擊長空的雄鷹,仰視一望無際的大地;愚笨的人學習,漫無目的,猶如亂飛亂撞的無頭飛蛾;刻苦的人學習,像彎彎的河流,雖有曲折,但終會流入大海;懶惰的人學習,像水中的木頭,阻力越大倒退得越快。
//myGraph.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h>#define MAX_VERTEX_NUM 20typedef int QElemType; typedef int VRType; typedef char VertexType; typedef enum {DG,UDG} GKind; //{有向圖,無向圖}typedef struct QNode {QElemType data;struct QNode *next; }QNode,*QPtr;typedef struct {QPtr front;QPtr tail; }LinkQueue;typedef struct {VertexType vexs[MAX_VERTEX_NUM]; //頂點向量VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//鄰接矩陣int vexnum,arcnum; //頂點數和弧數GKind kind; //圖的種類標識 }MGraph;//初始化隊列 void InitQ(LinkQueue &Q); //從隊尾插入元素 void EnQueue(LinkQueue &Q,QElemType e); //從對首刪除元素 void DeQueue(LinkQueue &Q,QElemType &e); //隊列是否為空,為空返回1,否則返回0 int QEmpty(const LinkQueue &Q);//選擇創立圖的類型 void CreatGraph(MGraph &G); //創立無向圖 void CreatUDG(MGraph &G); //創立有向圖 void CreatDG(MGraph &G); //打印鄰接矩陣 void printArcs(const MGraph &G); //返回字符在定點向量中的下標值 int LocateVex(const MGraph &G,VertexType ch); //深度優先遍歷函數 void DFSTraverse(const MGraph &G); void DFS(const MGraph &G,int v); //廣度優先遍歷函數 void BFSTraverse(const MGraph &G); //失掉第一個未被訪問的相鄰節點下標,若無,則返回-1 int firstAjdVex(const MGraph &G,int v); //失掉下一個未被訪問的相鄰節點下標,若無,則返回-1 int nextAjdVex(const MGraph &G,int v,int w); int *visited; //記錄頂點是否被訪問//主函數 int main() {MGraph G;CreatGraph(G);printf("\n原始連接矩陣:\n");printArcs(G);//深度優先遍歷結果printf("\n深度優先遍歷:");DFSTraverse(G);//廣度優先遍歷結果printf("\n廣度優先遍歷:");BFSTraverse(G);printf("\n");return 0;}//初始化隊列 void InitQ(LinkQueue &Q) {Q.front = Q.tail = (QPtr)malloc(sizeof(struct QNode));if ( !Q.front ){printf("InitQ分配內存出錯!\n");return ;} Q.front->next = NULL; }//從隊尾插入元素 void EnQueue(LinkQueue &Q,QElemType e) {QPtr q = (QPtr)malloc(sizeof(struct QNode));if ( !q ){printf("EnQueue分配內存出錯!\n");return ;}q->data = e;q->next = NULL;Q.tail->next = q; //如果是第一次插入,Q.front->next也指向了qQ.tail = q; }//從對首刪除元素 void DeQueue(LinkQueue &Q,QElemType &e) {if ( Q.front == Q.tail ){printf("DeQueue隊列為空,不能刪除元素!\n");return ;}QPtr q = Q.front->next;e = q->data;Q.front->next = q->next;if ( Q.tail == q )Q.tail = Q.front;free(q); }//隊列是否為空,為空返回1,否則返回0 int QEmpty(const LinkQueue &Q) {if ( Q.front == Q.tail ){return 1;}else{return 0;} }//選擇創立圖的類型 void CreatGraph(MGraph &G) {int k;printf("---------------------\n創立有向圖,輸入0;\n創立無\ 向圖,輸入1;\n并按下確認鍵.\n---------------------\n輸入:");scanf("%d",&k);switch(k){case 0:G.kind = DG;CreatDG(G);break;case 1:G.kind = UDG;CreatUDG(G);break;default:printf("圖類型輸入有誤!");break;} }//創立無向圖 void CreatUDG(MGraph &G) {int i,j,k,w;char v1,v2;printf("輸入頂點數和邊數:");scanf("%d%d",&G.vexnum,&G.arcnum); visited = (int *)malloc(G.vexnum*sizeof(int));for ( i = 0; i < G.vexnum; i++ )visited[i] = 0;printf("請按次序輸入%d個頂點字母標號(如ABC等):",G.vexnum);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; i++ )scanf("%c",&G.vexs[i]);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; ++i )for ( j = 0; j < G.vexnum; ++j ){//初始化鄰接矩陣if ( i == j )G.arcs[i][j] = 0;elseG.arcs[i][j] = INT_MAX;}printf("輸入邊的頂點和權值(如A B 1):\n");for ( k = 0; k < G.arcnum; k++ ){scanf("%c %c %d",&v1,&v2,&w);i = LocateVex(G,v1);j = LocateVex(G,v2);G.arcs[i][j] = w;G.arcs[j][i] = w;getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵} }//創立有向圖 void CreatDG(MGraph &G) {//和創立無向圖類似,只是少了一句將G.arcs[j][i] = w;//因為無向圖是對稱的,而有向圖不是int i,j,k,w;char v1,v2;printf("輸入頂點數和邊數:");scanf("%d%d",&G.vexnum,&G.arcnum); visited = (int *)malloc(G.vexnum*sizeof(int));for ( i = 0; i < G.vexnum; i++ )visited[i] = 0;printf("請按次序輸入%d個頂點字母標號(如ABC等):",G.vexnum);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; i++ )scanf("%c",&G.vexs[i]);getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵for ( i = 0; i < G.vexnum; ++i )for ( j = 0; j < G.vexnum; ++j ){//初始化鄰接矩陣if ( i == j )G.arcs[i][j] = 0;elseG.arcs[i][j] = INT_MAX;}printf("輸入邊的頂點和權值(如A B 1):\n");for ( k = 0; k < G.arcnum; k++ ){scanf("%c %c %d",&v1,&v2,&w);i = LocateVex(G,v1);j = LocateVex(G,v2);G.arcs[i][j] = w;getchar();//彈出緩沖區中前次最后出入的換行符,即最后按下的回車鍵} }//打印鄰接矩陣 void printArcs(const MGraph &G) {int i;int j;for ( i = 0; i < G.vexnum; i++ ){for ( j = 0; j < G.vexnum; j++ ){if ( INT_MAX == G.arcs[i][j])printf("%6s%","INF");else printf("%6d",G.arcs[i][j]);} printf("\n");} }//返回字符在定點向量中的下標值 int LocateVex(const MGraph &G,VertexType ch) {int i;for ( i = 0; G.vexnum; i++ )if ( ch == G.vexs[i] )return i;return -1; }//深度優先遍歷函數 void DFSTraverse(const MGraph &G) {int i;for ( i = 0; i < G.vexnum; i++ )visited[i] = 0; //初始化訪問標記數組for ( i = 0; i < G.vexnum; i++ )if ( !visited[i] ){//對尚未訪問的頂點調用DFSDFS(G,i);}printf("\n"); }void DFS(const MGraph &G,int v) {int w;visited[v] = 1;printf("%-4c",G.vexs[v]);for ( w = firstAjdVex(G,v); w >= 0; w = nextAjdVex(G,v,w) )if ( !visited[w] )DFS(G,w); }//廣度優先遍歷函數 void BFSTraverse(const MGraph &G) {int i,w,v;LinkQueue Q;InitQ(Q);for ( i = 0; i < G.vexnum; i++ )visited[i] = 0; //初始化訪問標記數組for ( i = 0; i < G.vexnum; i++ ){if ( !visited[i] ){visited[i] = 1;printf("%-4c",G.vexs[i]);EnQueue(Q,i);while (!QEmpty(Q)){DeQueue(Q,v);for ( w = firstAjdVex(G,v); w >= 0; w = nextAjdVex(G,v,w) ){if ( !visited[w] ){visited[w] = 1;printf("%-4c",G.vexs[w]);EnQueue(Q,w);}}}}}}//失掉第一個未被訪問的相鄰節點下標,若無,則返回-1 int firstAjdVex(const MGraph &G,int v) {int i;for ( i = 0; i < G.vexnum; i++ ){if ( !visited[i] && G.arcs[v][i] > 0 && G.arcs[v][i] < INT_MAX)return i;}return -1; }//失掉下一個未被訪問的相鄰節點下標,若無,則返回-1 int nextAjdVex(const MGraph &G,int v,int w) {int i;for ( i = w; i < G.vexnum; i++ ){if ( !visited[i] && G.arcs[v][i] > 0 && G.arcs[v][i] < INT_MAX)return i;}return -1; }
????程序運行結果(參照下面給出的例子):
????
?
?
文章結束給大家分享下程序員的一些笑話語錄: 系統程序員
1、頭皮經常發麻,在看見一個藍色屏幕的時候比較明顯,在屏幕上什幺都看不見的時候尤其明顯;
2、乘電梯的時候總擔心死機,并且在墻上找reset鍵;
3、指甲特別長,因為按F7到F12比較省力;
4、只要手里有東西,就不停地按,以為是Alt-F、S;
5、機箱從來不上蓋子,以便判斷硬盤是否在轉;
6、經常莫名其妙地跟蹤別人,手里不停按F10;
7、所有的接口都插上了硬盤,因此覺得26個字母不夠;
8、一有空就念叨“下輩子不做程序員了”;
9、總是覺得9號以后是a號;
10、不怕病毒,但是很害怕自己的程序;
總結
- 上一篇: 9.Tornado下的一个简易Blog-
- 下一篇: 关于js中的命名