PS:圖在數據結構中有着很是大的份量,它比樹有着更爲複雜的形式結構,這裏就再也不說圖的基本概念,直接就說圖的存儲結構,鄰接矩陣和鄰接表。圖是有方向的,有方向的叫作弧,無方向的叫作邊。存儲圖中各頂點自己數據,使用一維數組就足夠了;存儲頂點之間的關係時,要記錄每一個頂點和其它全部頂點之間的關係,因此須要使用二維數組。圖在大多行業中的使用也是不少的,好比說遊戲中兩我的物的尋址,自動尋路,就是圖與圖直接通過計算而後移動。後序還會介紹Dijkstra(迪傑斯特拉)算法計算最短路徑問題。linux
下面介紹鄰接矩陣原理:算法
下面能夠看到頂點之間有必定的聯繫,若是想要把他們存放在計算機中怎麼存入呢,首先咱們想到的是把頂點存在一維數組中,那麼他們的關係存在在二維數組中,就好像是以下格式,A->B 權值是10,B->E 權值30。(下方1爲有關係,0爲沒有關係,未加入權值)數組
首先把要知道頂點和邊數,而後單獨把頂點存在一維數組中,根據邊來肯定兩個頂點之間的聯繫,好比說第一條邊,是A->B。歸根結底也是經過數組來存儲。固然這是鄰接矩陣。數據結構
typedef char VertexType; typedef int EdgeType; #define MAXVEX 100 #define IUNFINITY 65535 typedef struct { VertexType vexs[MAXVEX]; /* 頂點表*/ EdgeType arc[MAXVEX][MAXVEX]; /* 鄰接矩陣 */ int vnum, edgenum; /*定點的個數和邊的個數*/ } MGraphy;
代碼中有不少註釋,有沒有用到的,可是一種經驗。 函數
//加入權值 void createGraphyWeight(MGraphy *g) { printf("輸入總頂點(空格)邊數\n"); scanf("%d %d", &g->vnum, &g->edgenum); printf("輸入 頂點表示:\n"); //頂點請輸入; for (int i = 0; i < g->vnum; i++) { printf("請輸入第%d個頂點", (i + 1)); // fflush(stdin);//不起做用,資料顯示一些linux平臺下一些庫沒有定義這個方法。 // flushall(); //清除多餘的回車符。 //若是不加入getchar的話,在for循環中就會先執行一遍scanf,由於上面可能會有一些回車,致使執行一遍scanf。須要清除以前的回車。 getchar(); scanf("%c", &g->vexs[i]); } for (int i = 0; i < g->vnum; i++) { // 初始化數組元素 Infonity for (int j = 0; j < g->vnum; j++) { // g->arc[i][j] = IUNFINITY;//對於加權值的默認所有設置爲最大值, g->arc[i][j] = 0;//對於未加權值的默認所有設置爲0 } } printf("輸入邊有關的兩個頂點,\n"); for (int i = 0; i < g->edgenum; i++) { char a, b; int c ; printf("輸入第 %d 條邊有關的兩個頂點加權值(空格隔開),沒有權值輸入0\n ", (i + 1)); getchar(); // setbuf(stdin,NULL); scanf("%c %c %d", &a, &b,&c); int ii = localGV(g, a); int jj = localGV(g, b); if(c == 0){ c=1; } // printf("c的值是%d",c); g->arc[ii][jj] = c; g->arc[jj][ii] = c; // 無向圖 } printfL(g); }
void printfL(MGraphy *g) { //輸出圖的信息 printf("表爲 :\n"); int i = 0; //先打印行標題;頂點標題 for (i = 0; i < g->vnum + 1; i++) { if (i > 0) { printf("%c\t", g->vexs[i - 1]); } else { printf("\\\t"); } } printf("\n"); for (i = 0; i < g->vnum; i++) { printf("%c\t", g->vexs[i]); for (int j = 0; j < g->vnum; j++) { printf("%d\t", g->arc[i][j]); } printf("\n"); } }
這裏的深度優先遍歷只給出代碼,原理後序會給出。調試
//深度優先搜索 void DFSTraverse(MGraphy *G){// int v; //將用作標記的visit數組初始化爲false for( v = 0; v < G->vnum; ++v){ visited[v] = false; } //對於每一個標記爲false的頂點調用深度優先搜索函數 for( v = 0; v < G->vnum; v++){ //若是該頂點的標記位爲false,則調用深度優先搜索函數 if(!visited[v]){ DFS(G, v); } } } int FirstAdjVex(MGraphy *g,int v) { //查找與數組下標爲v的頂點之間有邊的頂點,返回它在數組中的下標 for(int i = 0; i<g->vnum; i++){ if( g->arc[v][i]){ return i; } } return -1; } int NextAdjVex(MGraphy *G,int v,int w) { //從前一個訪問位置w的下一個位置開始,查找之間有邊的頂點 for(int i = w+1; i<G->vnum; i++){ //最關鍵的一個判斷,調試了好久,讓其等於'1'或者 !=0 ,不然該字符不知道後面仍是否有值相鏈接。 if(G->arc[v][i] != 0){ return i; } } return -1; } void DFS(MGraphy *g,int v){ visited[v]= true; printf("%c",g->vexs[v]);//輸入data值 //從該頂點的第一個邊開始,一直到最後一個邊,對處於邊另外一端的頂點調用DFS函數 int w; for( w= FirstAdjVex(g,v); w>=0; w = NextAdjVex(g,v,w)){ //若是該頂點的標記位false,證實未被訪問,調用深度優先搜索函數 if(!visited[w]){ DFS(g,w); } } }
完blog