• C++图的建立---邻接矩阵-----邻接表


    目录

    图的表示方式

     邻接矩阵

    邻接表

    图的遍历

    深度优先遍历

    深度优先遍历算法步骤: 

    图的广度优先遍历 

    广度优先遍历算法步骤: 

    图的邻接矩阵存储来创建图

    代码 

    运行结果: 

     图的邻接表存储来创建图

    如下图:

    运行结果:


    图的表示方式

    • 图的表示方式有两种:
    • 二维数组表示(邻接矩阵);链表表示(邻接表) 

     邻接矩阵

    ​ 邻接矩阵 邻接矩阵:邻接矩阵 是表示图形中顶点之间相邻关系的矩阵 

    邻接表

    1.  邻接矩阵需要为每个顶点都分配 n 个边的空间,其实有很多边都是不存在的,会造成空间的一定损失.
    2. 邻接表的实现只关心存在的边,不关心不存在的边。因此没有空间浪费,邻接表由数组+链表组成.

    图的遍历

    • 所谓图的遍历,即是对结点的访问。一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略:
    1. 深度优先遍历
    2. 广度优先遍历

    深度优先遍历

    • 深度优先遍历算法步骤: 

    1. 访问初始结点 v,并标记结点 v 为已访问
    2. 查找结点 v 的第一个邻接结点 w
    3. 若 w 存在,则继续访问 4,如果 w 不存在,则回到第 1 步,将从 v 的下一个结点继续
    4. 若 w 未被访问,对 w 进行深度优先遍历递归(即把 w 当作另一个 v ,然后进行步骤 123)
    5. 查找结点 v 的 w 邻接结点的下一个邻接结点,转到步骤 3
       
    • 核心代码: 
    1. //深度优先遍历
    2. void MyGraph::DFSearch(int v) {
    3. cout << vertex[v]<<" ";
    4. visited[v] = 1;
    5. for (int i = 0; i < vertexNum; i++) {
    6. if (edge[v][i] == 1 && visited[i] == 0) {
    7. DFSearch(i);
    8. }
    9. }
    10. }

    图的广度优先遍历 

    • 图的广度优先遍历(Broad First Search)
    • 类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点

    广度优先遍历算法步骤: 

    1. 访问初始结点 v 并标记结点 v 为已访问
    2. 结点 v 入队列
    3. 当队列非空时,继续执行,否则算法结束
    4. 出队列,取得头结点 u
    5. 查找结点 u 的第一个邻接结点 w
    6. 若结点 u 的邻接结点 w 不存在,则转到步骤 3;否则循环执行以下三个步骤
    1. >>若结点 w 尚未被访问,则访问结点 w 并标记为已访问
    2. >>结点 w 入队列
    3. >>查找结点 u 的继 w 邻接结点后的下一个邻接结点 w,转到步骤6
    •  核心代码
    1. //广度优先遍历
    2. void MyGraph::BFSearch(int v){
    3. int w, j;
    4. int Q[MaxSize]; //采用顺序队列
    5. int front=-1, rear=-1; //初始化队列
    6. cout << vertex[v] << " ";
    7. visited[v] = 1;
    8. Q[++rear] = v; //被访问的顶点入队
    9. while (front != rear) {
    10. w = Q[++front];//将对头元素出队并送到v中
    11. for (j = 0; j < vertexNum; j++) {
    12. if (edge[w][j] == 1 && visited[j] == 0) {
    13. cout << vertex[j] << " ";
    14. visited[j] = 1;
    15. Q[++rear] = j;
    16. }
    17. }
    18. }
    19. }

    图的邻接矩阵存储来创建图

    • 代码 

    1. /*
    2. * 图的邻接矩阵存储----
    3. * 图的建立与遍历:
    4. * 广度优先遍历---深度优先遍历
    5. */
    6. #include
    7. using namespace std;
    8. const int MaxSize = 10;
    9. int visited[MaxSize] = { 0 };//全局变量visited初始化——遍历的标志
    10. class MyGraph {
    11. private:
    12. char vertex[MaxSize];//存放顶点的数组
    13. char edge[MaxSize][MaxSize];//存放边的数组
    14. int vertexNum;//图的顶点数
    15. int edgeNum;//图的边数
    16. public:
    17. MyGraph(char a[], int n, int e);//传数组,顶点数,边数
    18. ~MyGraph();
    19. void DFSearch(int v);//深度优先遍历
    20. void BFSearch(int v);//广度优先遍历
    21. };
    22. //图的建立
    23. MyGraph::MyGraph(char a[], int n, int e){
    24. int i, j, k;
    25. this->vertexNum = n; //图的顶点数
    26. this->edgeNum = e; //图的边数
    27. //储存顶点
    28. for (i = 0; i < vertexNum; i++) {
    29. vertex[i] = a[i];
    30. }
    31. //初始化邻接矩阵
    32. for (i = 0; i < vertexNum; i++) {
    33. for (j = 0; j < vertexNum; j++) {
    34. edge[i][j] = 0;
    35. }
    36. }
    37. cout << "请输入边依附的两个顶点的编号:" << endl;
    38. // 依次输入每一条边----无向图---对称,有向图--可能不对称
    39. for (k = 0; k < edgeNum; k++) {
    40. cin >> i >> j; //输入边依附的两个顶点的编号
    41. //无向图-- - 对称---有i j必有j i
    42. edge[i][j] = 1; edge[j][i] = 1; //置有边标志为1,没有默认为0
    43. }
    44. }
    45. //图的析构——图的邻接矩阵存储为静态存储分配,
    46. //在图变量退出作用域时自动释放所占内存单元,因此,
    47. //图的邻接矩阵存储无须销毁,析构函数为空
    48. MyGraph::~MyGraph(){}
    49. //深度优先遍历
    50. void MyGraph::DFSearch(int v) {
    51. cout << vertex[v]<<" ";
    52. visited[v] = 1;
    53. for (int i = 0; i < vertexNum; i++) {
    54. if (edge[v][i] == 1 && visited[i] == 0) {
    55. DFSearch(i);
    56. }
    57. }
    58. }
    59. //广度优先遍历
    60. void MyGraph::BFSearch(int v){
    61. int w, j;
    62. int Q[MaxSize]; //采用顺序队列
    63. int front=-1, rear=-1; //初始化队列
    64. cout << vertex[v] << " ";
    65. visited[v] = 1;
    66. Q[++rear] = v; //被访问的顶点入队
    67. while (front != rear) {
    68. w = Q[++front];//将对头元素出队并送到v中
    69. for (j = 0; j < vertexNum; j++) {
    70. if (edge[w][j] == 1 && visited[j] == 0) {
    71. cout << vertex[j] << " ";
    72. visited[j] = 1;
    73. Q[++rear] = j;
    74. }
    75. }
    76. }
    77. }
    78. int main() {
    79. int i;
    80. char array[] = { 'A','B','C','D','E' };
    81. MyGraph mygraph{ array,5,6 };//建立5个顶点,6条边的无向图
    82. //深度优先遍历
    83. for (i = 0; i < MaxSize; i++) {
    84. visited[i] = 0;
    85. }
    86. cout << "深度优先遍历序列为:";
    87. mygraph.DFSearch(0); //从顶点0出发进行深度优先遍历
    88. cout << endl;
    89. //广度优先遍历
    90. for (i = 0; i < MaxSize;i++) {
    91. visited[i] = 0;
    92. }
    93. cout << "广度优先遍历序列为:";
    94. mygraph.BFSearch(0); //从顶点0出发进行广度优先遍历
    95. return 0;
    96. }

    建立如下的无向图:

     

    运行结果: 

     图的邻接表存储来创建图

    1. /*
    2. * 图的邻接表存储----
    3. * 图的建立与遍历:
    4. * 广度优先遍历---深度优先遍历
    5. */
    6. #include
    7. using namespace std;
    8. const int MaxSize = 10;
    9. int visited[MaxSize] = { 0 };//全局变量visited初始化——遍历的标志
    10. //定义边表结点
    11. struct EdgeNode
    12. {
    13. int adjvex; //邻接点数据域
    14. EdgeNode* next;//邻接点指针域
    15. };
    16. //定义顶点表结点
    17. struct VertexNode
    18. {
    19. char vertex;
    20. EdgeNode* firstEdge;
    21. };
    22. class ALGraph
    23. {
    24. private:
    25. VertexNode adjlist[MaxSize]; //存放顶点表的数组
    26. int vertexNum; //图的顶点数
    27. int edgeNum; //图的边数
    28. public:
    29. ALGraph(char a[], int n, int e);
    30. ~ALGraph();
    31. void DFSearch(int v);//深度优先遍历
    32. void BFSearch(int v);//广度优先遍历
    33. };
    34. //有向图邻接表存储的构造函数
    35. ALGraph::ALGraph(char a[], int n, int e){
    36. int i, j, k;
    37. EdgeNode* s = nullptr;
    38. this->vertexNum = n;
    39. this->edgeNum = e;
    40. //输入顶点信息,初始化顶点表
    41. for (i = 0; i < vertexNum; i++) {
    42. adjlist[i].vertex = a[i];
    43. adjlist[i].firstEdge = nullptr;
    44. }
    45. cout << "请输入边依附的两个顶点的编号:"<
    46. //依次输入每条边
    47. for (k = 0; k < edgeNum; k++) {
    48. cin >> i >> j; //输入边依附的两个顶点的编号
    49. s = new EdgeNode;//生成一个边表结点s
    50. s->adjvex = j;
    51. s->next = adjlist[i].firstEdge;//将结点s插入表头
    52. adjlist[i].firstEdge = s;
    53. }
    54. }
    55. //图的销毁
    56. ALGraph::~ALGraph(){
    57. EdgeNode* p = nullptr, * q = nullptr;
    58. for (int i = 0; i < vertexNum; i++) {
    59. p = q = adjlist[i].firstEdge;
    60. while (p != nullptr) {
    61. p = q->next;
    62. delete q;
    63. q = p;
    64. }
    65. }
    66. }
    67. //深度优先遍历
    68. void ALGraph::DFSearch(int v) {
    69. int j;
    70. EdgeNode* p = nullptr;
    71. cout << adjlist[v].vertex; visited[v] = 1;
    72. p = adjlist[v].firstEdge;//工作指针p指向顶点v的边表
    73. while (p != nullptr) {
    74. j=p->adjvex;
    75. if (visited[j] == 0) {
    76. DFSearch(j);
    77. }
    78. p = p->next;
    79. }
    80. }
    81. //广度优先遍历
    82. void ALGraph::BFSearch(int v) {
    83. int w, j;
    84. int Q[MaxSize]; //采用顺序队列
    85. int front = -1, rear = -1; //初始化队列
    86. EdgeNode* p = nullptr;
    87. cout << adjlist[v].vertex<<" ";
    88. visited[v] = 1;
    89. Q[++rear] = v; //被访问的顶点入队
    90. while (front != rear) { //当队非空时
    91. w = Q[++front];
    92. p = adjlist[w].firstEdge;//工作指针p指向顶点v的边表
    93. while (p!=nullptr){
    94. j = p->adjvex;
    95. if (visited[j] == 0) {
    96. cout << adjlist[j].vertex << " ";
    97. visited[j] = 1;
    98. Q[++rear] = j;
    99. }
    100. p = p->next;
    101. }
    102. }
    103. }
    104. int main() {
    105. char array[] = { 'A','B','C','D','E' };;
    106. int i;
    107. ALGraph algraph{ array,5,6 };//建立5个顶点,6条边的无向图
    108. //深度优先遍历
    109. for (i = 0; i < MaxSize; i++) {
    110. visited[i] = 0;
    111. }
    112. cout << "深度优先遍历序列为:";
    113. algraph.DFSearch(0); //从顶点0出发进行深度优先遍历
    114. cout << endl;
    115. //广度优先遍历
    116. for (i = 0; i < MaxSize; i++) {
    117. visited[i] = 0;
    118. }
    119. cout << "广度优先遍历序列为:";
    120. algraph.BFSearch(0); //从顶点0出发进行广度优先遍历
    121. return 0;
    122. }

    如下图:

    运行结果:

     

     

  • 相关阅读:
    14. Redisson 分布式锁
    vue-别名路径联想提示的配置
    Linux操作系统之线程
    Python——基础语法(模块、包、文件读写等操作)
    利用PerconaTookit工具在线修改表结构
    Spring boot多数据源实现动态切换
    9.2作业
    【SpringMVC】JSON注解&全局异常处理机制
    JVM基础08_强软弱虚引用
    GB/T 10707 橡胶燃烧性能
  • 原文地址:https://blog.csdn.net/m0_63064861/article/details/127767017