• Day17:图


    目录

    一、基本概念 

     二、代码实现:

    ①代码的框架

     ②初始化、创建、show函数的实现

    ③寻找第一个临近节点,寻找第二个临近节点

    ④DFS和BFS

    一、基本概念 

    1.多对多的数据结构 - 图
    2.构成: 
            顶点                                                       vertexs
            边:   用来描述顶点之间的关系             edges
    3.描述图的方式:

            临接表:链表
            临接矩阵:数组

    4.网图:边有长度(权值)

                    A星寻路算法:
                        f = g + h
                        f = g + h + w其中的w就是可能的权值

    5.图的遍历:
            深度优先遍历:Deap First Search
                一路往下遍历,没有了再换周围其他节点
            广度优先遍历:Breadth First Search
                先把周围的遍历完,然后再往下搜索

    关键实现函数:

            找某个顶点的第一个相邻顶点
            找某个顶点的第二个相邻顶点

     二、代码实现:

    注:这里的DFS采用递归的方法实现.

    ①代码的框架

    1. include
    2. #include
    3. #include
    4. using namespace std;
    5. //临界矩阵描述图
    6. #define VERTEXS 6
    7. #define EDGES 7
    8. //图类型
    9. struct Graph
    10. {
    11. int vertexs; //顶点个数
    12. int edges; //边条数
    13. char* pVertex; //指向 存储所有顶点的一维数组
    14. int** pEdge; //二级指针 描述矩阵
    15. };
    16. //创建图对象
    17. Graph* createGraph();
    18. //初始化图对象
    19. void initGraph(Graph* g, int vertexs, int edges, char* v, int map[VERTEXS][VERTEXS]);
    20. //显示图对象
    21. void showGraph(Graph* g);
    22. //从图中找到参数顶点在顶点数组中的下标并返回
    23. int _getIndex(Graph* g, char c);
    24. //找beg参数对应顶点的第一个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过
    25. int findFirstVertex(Graph* g, int beg, bool isFind[VERTEXS]);
    26. //找beg参数对应顶点的第二个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过
    27. int findNextVertex(Graph* g, int beg, bool isFind[VERTEXS]);
    28. void DFS(Graph* g, char beg, bool isFind[VERTEXS]);
    29. void BFS(Graph* g, char beg, bool isFind[VERTEXS]);
    30. void travel(Graph* g, char beg,bool isD=true)
    31. {
    32. bool isFind[VERTEXS] = { 0 };
    33. if (isD)
    34. {
    35. printf("深度优先遍历:%c ", beg);
    36. DFS(g, beg, isFind);
    37. printf("\n");
    38. }
    39. else
    40. {
    41. printf("广度优先遍历:%c ", beg);
    42. BFS(g, beg, isFind);
    43. printf("\n");
    44. }
    45. }
    46. int main()
    47. {
    48. Graph* g = createGraph();
    49. char buff[7] = "ABCDEF";
    50. int map[VERTEXS][VERTEXS] =
    51. {
    52. { 0, 1, 0, 1, 0, 0 },
    53. { 1, 0, 1, 0, 0, 0 },
    54. { 0, 1, 0, 1, 1, 1 },
    55. { 1, 0, 1, 0, 0, 1 },
    56. { 0, 0, 1, 0, 0, 0 },
    57. { 0, 0, 1, 1, 0, 0 }
    58. };
    59. initGraph(g, VERTEXS, EDGES, buff, map);
    60. showGraph(g);
    61. // travel(g, 'A');
    62. travel(g, 'A',1);
    63. while (1);
    64. return 0;
    65. }

     ②初始化、创建、show函数的实现

    1. //创建图对象
    2. Graph* createGraph()
    3. {
    4. Graph* pNew = new Graph;
    5. if (NULL == pNew) return NULL;
    6. memset(pNew, 0, sizeof(Graph));
    7. return pNew;
    8. }
    9. //初始化图对象
    10. void initGraph(Graph* g, int vertexs, int edges, char* v, int map[VERTEXS][VERTEXS])
    11. {
    12. #if 1
    13. //1 开内存
    14. g->vertexs = vertexs;
    15. g->edges = edges;
    16. g->pVertex = new char[g->vertexs];
    17. g->pEdge = new int*[g->vertexs];
    18. for (int i = 0; i < g->vertexs; i++)
    19. {
    20. g->pEdge[i] = new int[g->vertexs];
    21. }
    22. //2 数据拷贝
    23. memcpy(g->pVertex, v, sizeof(char)*g->vertexs);
    24. for (int i = 0; i < g->vertexs; i++)
    25. {
    26. memcpy(g->pEdge[i], map[i], sizeof(int)*g->vertexs);
    27. }
    28. #else
    29. //1 开内存
    30. //此处最好也是用户输入
    31. g->vertexs = vertexs;
    32. g->edges = edges;
    33. g->pVertex = new char[g->vertexs];
    34. g->pEdge = new int*[g->vertexs];
    35. for (int i = 0; i < g->vertexs; i++)
    36. {
    37. g->pEdge[i] = new int[g->vertexs];
    38. memset(g->pEdge[i], 0, sizeof(int)*g->vertexs);
    39. }
    40. printf("请输入顶点:");
    41. scanf("%s", g->pVertex);//输入的时候自行把握 不要越界
    42. char buff[5] = { 0 };
    43. char src, dst;
    44. int srcIdx, dstIdx;
    45. for (int i = 0; i < g->edges; i++)
    46. {
    47. printf("请输入第%d条边:", i + 1);
    48. scanf("%s", buff);// A->B
    49. src = buff[0];
    50. dst = buff[3];
    51. srcIdx = _getIndex(g, src);
    52. dstIdx = _getIndex(g, dst);
    53. g->pEdge[srcIdx][dstIdx] = 1;
    54. #if 1 //如果是无向图 加这一行
    55. g->pEdge[dstIdx][srcIdx] = 1;
    56. #endif
    57. }
    58. #endif
    59. }
    60. //从图中找到参数顶点在顶点数组中的下标并返回
    61. int _getIndex(Graph* g, char c)
    62. {
    63. for (int i = 0; i < g->vertexs; i++)
    64. {
    65. if (c == g->pVertex[i]) return i;
    66. }
    67. return -1;
    68. }
    69. //显示图对象
    70. void showGraph(Graph* g){
    71. for (int i = 0; i <= g->vertexs; i++)
    72. {
    73. for (int j = 0; j <= g->vertexs; j++)
    74. {
    75. if (0 == i && 0 == j)
    76. {
    77. printf(" ");
    78. }
    79. else if (0 == i)
    80. {//第一行
    81. printf("%c ", g->pVertex[j - 1]);
    82. }
    83. else if (0 == j)
    84. {//第一列
    85. printf("%c ", g->pVertex[i - 1]);
    86. }
    87. else
    88. {//才是里面对应的数字
    89. printf("%d ", g->pEdge[i - 1][j - 1]);
    90. }
    91. }
    92. printf("\n");
    93. }
    94. }

    ③寻找第一个临近节点,寻找第二个临近节点

    1. //找beg参数对应顶点的第一个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过
    2. int findFirstVertex(Graph* g, int beg, bool isFind[VERTEXS])
    3. {
    4. for (int i = 0; i < g->vertexs; i++)
    5. {
    6. if (isFind[i]) continue;
    7. if (1 == g->pEdge[beg][i]) return i; //找到beg对应的那一行,邻接矩阵中遇到的第一个就是第一个相邻的顶点
    8. }
    9. return -1;
    10. }
    11. //找beg参数对应顶点的第二个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过
    12. int findNextVertex(Graph* g, int beg, bool isFind[VERTEXS])
    13. {
    14. for (int i = beg+1; i < g->vertexs; i++)
    15. {//注:为什么i是从beg+1开始的,是因为用的时候传入的CurrentIdx,也就是第一次找到的下标---->+1就能从后面开始搜
    16. if (isFind[i]) continue;
    17. if (1 == g->pEdge[beg][i]) return i;
    18. }
    19. return -1;
    20. }

    ④DFS和BFS

    1. //递归实现栈的回退
    2. void DFS(Graph* g, char beg, bool isFind[VERTEXS])
    3. {
    4. //找beg的第一个相邻顶点x ,继续找x的第一个相邻顶点y 直到没有找到 结束
    5. int currentIdx = _getIndex(g,beg);
    6. isFind[currentIdx] = 1;//每递归到一个,就标记一个.
    7. int nextIdx = findFirstVertex(g, currentIdx, isFind);
    8. while (1)
    9. {
    10. if (-1 == nextIdx) break;
    11. if (false == isFind[nextIdx])
    12. {
    13. printf("%c ", g->pVertex[nextIdx]);
    14. DFS(g, g->pVertex[nextIdx],isFind);
    15. }
    16. nextIdx = findNextVertex(g, currentIdx, isFind);
    17. }
    18. }
    19. void BFS(Graph* g, char beg, bool isFind[VERTEXS])
    20. {
    21. queue<int> q;
    22. q.push(_getIndex(g, beg));//把第一个放到队列里
    23. isFind[_getIndex(g, beg)] = true;
    24. int headIdx;
    25. int idx;
    26. while (!q.empty())
    27. {//step1:找出队首的元素,保存并在队列中删除
    28. headIdx = q.front();//队列头 第一个
    29. q.pop();//删掉第一个
    30. //step2:把刚才保存的顶点的相邻的顶点都放到队列中
    31. idx = findFirstVertex(g, headIdx, isFind);//找到头结点的邻接的结点 while 找出全部的.
    32. while (1)
    33. {
    34. if (-1 == idx) break;
    35. if (!isFind[idx])
    36. {
    37. isFind[idx] = true;//每push进去一个,就标记一个
    38. printf("%c ", g->pVertex[idx]);
    39. q.push(idx);
    40. }
    41. idx = findNextVertex(g, headIdx, isFind);
    42. }
    43. }
    44. }

  • 相关阅读:
    DPDK和VPP地址池
    主成分分析法(数学建模)教授先生
    Gitlab-runner+Docker自动部署SpringBoot项目
    NX二次开发-UFUN按类型遍历名字获取Tag函数UF_OBJ_cycle_by_name_and_type
    Flink SQL(四) 连接到外部系统Elasticsearch和HBase
    SWUST OJ#99 欧几里得博弈
    PAT 1029 旧键盘
    网络编程——封装和分用(图解)
    【微服务】分布式下服务调用产生的问题之服务容错
    聊聊Spring Cloud Gateway 动态路由及通过Apollo的实现
  • 原文地址:https://blog.csdn.net/zjjaibc/article/details/126376612