1. 程式人生 > >博客作業—圖

博客作業—圖

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. 閱讀代碼

六度空間是一個看似復雜的大數據結構,但經過圖結構的簡化,將人與人的關系建立起來,

更好地判斷他們的關系,足以見得圖結構的優勢

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. #define MAX 10001//最大頂點數
  4. /**
  5. *解題思想:
  6. *對圖進行廣度搜索
  7. *得出每層中的頂點數
  8. *計算百分比
  9. */
  10. int BFS(int i, int N, int ** snap)
  11. {// 隊列 遍歷登記 隊頭 隊尾 計數器 層數
  12. int q[MAX], visit[MAX], front, rear, count, level, last, tail, v, j;
  13. for (j = 0; j < 10001; j++)//初始化數組
  14. visit[j] = 0;
  15. visit[i] = 1;//開始結點
  16. front = rear = -1;//隊列初始化
  17. count = 1;//計算六度空間的個數
  18. level = 0;//level計算層數,等於6時跳出
  19. last = i;//last為上一層最後的頂點
  20. q[++rear] = i;//入隊 當前頂點所在層數
  21. while (front<rear) //遍歷隊列(六層以內)
  22. {
  23. /*
  24. *圖的廣度搜索原理解析:
  25. *類似二叉樹的層序遍歷
  26. *1、從所需要的頂點進入圖(類似利用此頂點為樹的根結點,構建一棵樹)
  27. *2、根結點入隊列
  28. *3、尋找與此頂點相連的所有頂點並放入隊列中(圖的臨接矩陣中,儲存的是每個頂點間的邊的關系,而且無向圖的臨接矩陣一定為對稱矩陣)
  29. *4、當頂點所在行遍歷結束,取出隊列的下一個頂點,重復。直至遍歷所有的頂點
  30. */
  31. v = q[++front]; //出隊
  32. for (j = 1; j <= N; j++)//遍歷
  33. if (!visit[j] && snap[v][j] == 1)
  34. {//當結點沒有記錄而且此處結點為頂點時
  35. q[++rear] = j;//入隊列
  36. visit[j] = 1;//記錄對應位置
  37. count++;//計數器
  38. tail = j;//tail是當前層的最後一個頂點
  39. }
  40. if (v == last)
  41. {
  42. level++;//層數加一
  43. last = tail;//記錄最後一個頂點
  44. }
  45. if (6 == level)//等於六層時,退出循環
  46. break;
  47. }
  48. return count;//返回六度空間內所有頂點數
  49. }
  50. int main(void)
  51. {
  52. int N, M;
  53. int count = 0;
  54. scanf("%d %d", &N, &M);
  55. int **snap;//實現動態分配二維數組
  56. /*註意:
  57. *******動態分配必須按照順序分配
  58. *******同時數組釋放內存的時候要按照先後順序釋放
  59. *******否則會出現野指針
  60. *******內存泄漏導致程序崩潰
  61. */
  62. snap = (int**)malloc(sizeof(int*) * (N + 1));
  63. if (snap == NULL)
  64. return -1;
  65. //動態分配內存存在失敗的可能,所以
  66. //在進行動態分配內存後
  67. //應該進行對應的指針是否為空指針的判斷
  68. int i, x, y, j;
  69. for (i = 0; i <= N; i++)
  70. {
  71. *(snap + i) = (int *)malloc(sizeof(int) * (N + 1));
  72. if (*(snap + i) == NULL)
  73. return -1;
  74. }
  75. for (i = 0; i < M; i++)
  76. {
  77. scanf("%d %d", &x, &y);//無向圖對角線對稱
  78. snap[x][y] = snap[y][x] = 1;//關系對等
  79. }
  80. for (i = 1; i <= N; i++)
  81. {
  82. count = BFS(i, N, snap);
  83. printf("%d: %.2f%%\n", i, (float)count / N * 100);
  84. }
  85. //直接進行頭指針的內存釋放不全等於所有指針內存的釋放
  86. //free(snap);
  87. for (i = 0; i < N; i++)
  88. {
  89. free(*(snap + i));
  90. *(snap + i) = NULL;
  91. }
  92. free(snap);
  93. snap = NULL;
  94. return 0;
  95. }

博客作業—圖