博客作業—圖
阿新 • • 發佈:2018-06-17
i++ span 等於 有向圖 img 復雜 重點 eof 表示
1.學習總結
1.1圖的思維導圖
1.2 圖結構學習體會
談談你對圖結構中的幾個經典算法學習體會。具體有:
- 深度遍歷算法和廣度遍歷算法:理解起來相對容易,尤其是在鄰接矩陣中,找起來很方便,重要的就是要細心,做到不重不漏
- Prim和Kruscal算法:prim算法把頂點分成已選和未選的思路很好,但相比來說kruscal算法找最小邊更為精確,代碼量也小
- Dijkstra算法:時間復雜度為O(n2),要很認真地去觀察新添頂點後,點與點之間的距離能不能更小
- 拓撲排序算法:一定要有向圖,要去判斷有沒有環路,有環路則為錯誤
2.PTA實驗作業
1.1 題目1:7-1 圖著色問題
1.2 設計思路
圖著色問題是一個著名的NP完全問題。給定無向圖,,問可否用K種顏色為V中的每一個頂點分配一種顏色,使得不會有兩個相鄰頂點具有同一種顏色?
但本題並不是要我們解決這個著色問題,而是對給定的一種顏色分配,判斷這是否是圖著色問題的一個解。
重點代碼流程為:使用回溯法將visited數組初始化為0-->依次觀察每一種顏色,若頂點之間的著色不沖突則轉下一步驟,否則繼續搜索-->若頂點全部著色,輸出數組
-->若頂點是一個合法著色,則轉處理下一個-->否則重置頂點顏色
1.3 代碼截圖
1.4 PTA提交列表說明
說明:主要是細節處理問題,自己應該清楚每個循環結構體開始和結束的地方!!!
2.1 題目2:7-2 排座位
2.2 設計思路
題目關於敵對和朋友問題說的很拗口,但簡化起來:關系
為1表示是朋友,-1表示是死對頭--->朋友兩頂點的權值為1,死對頭兩頂點權值為-1;
如果兩位賓客之間是朋友,且沒有敵對關系,則輸出No problem
;如果他們之間並不是朋友,但也不敵對,則輸出OK
;如果他們之間有敵對,然而也有共同的朋友,則輸出OK but...
;如果他們之間只有敵對關系,則輸出No way
。---->權值為1,No problem;沒有連接,OK;有共同根,OK but...;權值為-1,No way。代碼主要就是建圖和判斷兩點關系。
2.3 代碼截圖
2.4 PTA提交列表說明
說明:沒註意看清輸出要求裏面大小寫和點,以後要認真審題!!!
3.1 題目3:7-5 暢通工程之最低成本建設問題
3.2 設計思路
成本問題就是最短路徑問題,用最小生成樹來求解問題,由輸入數據建立帶權的無向圖,判斷兩頂點(兩城鎮)的
最短路徑(最低成本建設)。
3.3 代碼截圖
3.4 PTA提交列表說明
說明:對Prim算法的熟練度不夠,改動課本源代碼比較慢。
3.截圖本周題目集的PTA最後排名
4. 閱讀代碼
六度空間是一個看似復雜的大數據結構,但經過圖結構的簡化,將人與人的關系建立起來,
更好地判斷他們的關系,足以見得圖結構的優勢
- #include<stdio.h>
- #include<malloc.h>
- #define MAX 10001//最大頂點數
- /**
- *解題思想:
- *對圖進行廣度搜索
- *得出每層中的頂點數
- *計算百分比
- */
- int BFS(int i, int N, int ** snap)
- {// 隊列 遍歷登記 隊頭 隊尾 計數器 層數
- int q[MAX], visit[MAX], front, rear, count, level, last, tail, v, j;
- for (j = 0; j < 10001; j++)//初始化數組
- visit[j] = 0;
- visit[i] = 1;//開始結點
- front = rear = -1;//隊列初始化
- count = 1;//計算六度空間的個數
- level = 0;//level計算層數,等於6時跳出
- last = i;//last為上一層最後的頂點
- q[++rear] = i;//入隊 當前頂點所在層數
- while (front<rear) //遍歷隊列(六層以內)
- {
- /*
- *圖的廣度搜索原理解析:
- *類似二叉樹的層序遍歷
- *1、從所需要的頂點進入圖(類似利用此頂點為樹的根結點,構建一棵樹)
- *2、根結點入隊列
- *3、尋找與此頂點相連的所有頂點並放入隊列中(圖的臨接矩陣中,儲存的是每個頂點間的邊的關系,而且無向圖的臨接矩陣一定為對稱矩陣)
- *4、當頂點所在行遍歷結束,取出隊列的下一個頂點,重復。直至遍歷所有的頂點
- */
- v = q[++front]; //出隊
- for (j = 1; j <= N; j++)//遍歷
- if (!visit[j] && snap[v][j] == 1)
- {//當結點沒有記錄而且此處結點為頂點時
- q[++rear] = j;//入隊列
- visit[j] = 1;//記錄對應位置
- count++;//計數器
- tail = j;//tail是當前層的最後一個頂點
- }
- if (v == last)
- {
- level++;//層數加一
- last = tail;//記錄最後一個頂點
- }
- if (6 == level)//等於六層時,退出循環
- break;
- }
- return count;//返回六度空間內所有頂點數
- }
- int main(void)
- {
- int N, M;
- int count = 0;
- scanf("%d %d", &N, &M);
- int **snap;//實現動態分配二維數組
- /*註意:
- *******動態分配必須按照順序分配
- *******同時數組釋放內存的時候要按照先後順序釋放
- *******否則會出現野指針
- *******內存泄漏導致程序崩潰
- */
- snap = (int**)malloc(sizeof(int*) * (N + 1));
- if (snap == NULL)
- return -1;
- //動態分配內存存在失敗的可能,所以
- //在進行動態分配內存後
- //應該進行對應的指針是否為空指針的判斷
- int i, x, y, j;
- for (i = 0; i <= N; i++)
- {
- *(snap + i) = (int *)malloc(sizeof(int) * (N + 1));
- if (*(snap + i) == NULL)
- return -1;
- }
- for (i = 0; i < M; i++)
- {
- scanf("%d %d", &x, &y);//無向圖對角線對稱
- snap[x][y] = snap[y][x] = 1;//關系對等
- }
- for (i = 1; i <= N; i++)
- {
- count = BFS(i, N, snap);
- printf("%d: %.2f%%\n", i, (float)count / N * 100);
- }
- //直接進行頭指針的內存釋放不全等於所有指針內存的釋放
- //free(snap);
- for (i = 0; i < N; i++)
- {
- free(*(snap + i));
- *(snap + i) = NULL;
- }
- free(snap);
- snap = NULL;
- return 0;
- }
博客作業—圖