在线绘图
    image.png
    https://csacademy.com/app/graph_editor/

    1. #include <iostream>
    2. #include <cstdlib>
    3. using namespace std;
    4. #define MVNum 100 //最大顶点数
    5. #define MAXQSIZE 100 //最大队列长度
    6. typedef char VerTexType; //假设顶点的数据类型为字符型
    7. typedef int ArcType; //假设边的权值类型为整型
    8. //------------图的邻接矩阵------------------
    9. typedef struct{
    10. VerTexType vexs[MVNum]; //顶点表
    11. ArcType arcs[MVNum][MVNum]; //邻接矩阵
    12. int vexnum,arcnum; //图的当前点数和边数
    13. }Graph;
    14. bool visited[MVNum]; //访问标志数组,其初值为"false"
    15. int FirstAdjVex(Graph G , int v); //返回v的第一个邻接点
    16. int NextAdjVex(Graph G , int v , int w); //返回v相对于w的下一个邻接点
    17. int LocateVex(Graph G , VerTexType v){
    18. //确定点v在G中的位置
    19. for(int i = 0; i < G.vexnum; ++i)
    20. if(G.vexs[i] == v)
    21. return i;
    22. return -1;
    23. }//LocateVex
    24. //----队列的定义及操作--------
    25. typedef struct{
    26. ArcType *base; //初始化的动态分配存储空间
    27. int front; //头指针,若队列不空,指向队头元素
    28. int rear; //尾指针,若队列不空,指向队尾元素的下一个位置
    29. }sqQueue;
    30. void InitQueue(sqQueue &Q){
    31. //构造一个空队列Q
    32. Q.base = new ArcType[MAXQSIZE];
    33. if(!Q.base) exit(1); //存储分配失败
    34. Q.front = Q.rear = 0;
    35. }//InitQueue
    36. void EnQueue(sqQueue &Q, ArcType e){
    37. //插入元素e为Q的新的队尾元素
    38. if((Q.rear + 1) % MAXQSIZE == Q.front)
    39. return;
    40. Q.base[Q.rear] = e;
    41. Q.rear = (Q.rear + 1) % MAXQSIZE;
    42. }//EnQueue
    43. bool QueueEmpty(sqQueue Q){
    44. //判断是否为空队
    45. if(Q.rear == Q.front)
    46. return true;
    47. return false;
    48. }//QueueEmpty
    49. void DeQueue(sqQueue &Q, ArcType &u){
    50. //队头元素出队并置为u
    51. u = Q.base[Q.front];
    52. Q.front = (Q.front + 1) % MAXQSIZE;
    53. }//DeQueue
    54. void CreateUDN(Graph &G){
    55. //采用邻接矩阵表示法,创建无向网G
    56. int i , j , k;
    57. cout <<"请输入总顶点数,总边数,以空格隔开:";
    58. cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
    59. cout << endl;
    60. cout << "输入点的名称,如a" <<endl;
    61. for(i = 0; i < G.vexnum; ++i){
    62. cout << "请输入第" << (i+1) << "个点的名称:";
    63. cin >> G.vexs[i]; //依次输入点的信息
    64. }
    65. cout << endl;
    66. for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
    67. for(j = 0; j < G.vexnum; ++j)
    68. G.arcs[i][j] = 0;
    69. cout << "输入边依附的顶点,如a b" << endl;
    70. for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
    71. VerTexType v1 , v2;
    72. cout << "请输入第" << (k + 1) << "条边依附的顶点:";
    73. cin >> v1 >> v2; //输入一条边依附的顶点及权值
    74. i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
    75. G.arcs[j][i] = G.arcs[i][j] = 1; //置<v1, v2>的对称边<v2, v1>的权值为w
    76. }//for
    77. }//CreateUDN
    78. void DFS(Graph G, int v){
    79. //图G为邻接矩阵类型
    80. int w;
    81. cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
    82. for(w = 0; w < G.vexnum; w++) //依次检查邻接矩阵v所在的行
    83. if((G.arcs[v][w] != 0)&& (!visited[w])) DFS(G, w); //G.arcs[v][w]!=0表示w是v的邻接点,如果w未访问,则递归调用DFS
    84. }//DFS
    85. void BFS (Graph G, int v){
    86. //按广度优先非递归遍历连通图G
    87. sqQueue Q;
    88. ArcType u;
    89. ArcType w;
    90. cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
    91. InitQueue(Q); //辅助队列Q初始化,置空
    92. EnQueue(Q, v); //v进队
    93. while(!QueueEmpty(Q)){ //队列非空
    94. DeQueue(Q, u); //队头元素出队并置为u
    95. for(w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w)){
    96. //依次检查u的所有邻接点w ,FirstAdjVex(G, u)表示u的第一个邻接点
    97. //NextAdjVex(G, u, w)表示u相对于w的下一个邻接点,w≥0表示存在邻接点
    98. if(!visited[w]){ //w为u的尚未访问的邻接顶点
    99. cout << G.vexs[w] << " "; visited[w] = true; //访问w,并置访问标志数组相应分量值为true
    100. EnQueue(Q, w); //w进队
    101. }//if
    102. }//for
    103. }//while
    104. }//BFS
    105. int FirstAdjVex(Graph G , int v){
    106. //返回v的第一个邻接点
    107. int i;
    108. for(i = 0 ; i < G.vexnum ; ++i){
    109. if(G.arcs[v][i] == 1 && visited[i] == false)
    110. return i;
    111. }
    112. return -1;
    113. }//FirstAdjVex
    114. int NextAdjVex(Graph G , int v , int w){
    115. //返回v相对于w的下一个邻接点
    116. int i;
    117. for(i = w ; i < G.vexnum ; ++i){
    118. if(G.arcs[v][i] == 1 && visited[i] == false)
    119. return i;
    120. }
    121. return -1;
    122. }//NextAdjVex
    123. int main(){
    124. cout << "*****************采用邻接矩阵表示图的深度、广度优先搜索遍历**************" << endl << endl;
    125. Graph G;
    126. CreateUDN(G);
    127. cout << endl;
    128. cout << "无向图G创建完成!" << endl << endl;
    129. cout << "请输入遍历无向图G的起始点:";
    130. VerTexType c;
    131. cin >> c;
    132. int i;
    133. for(i = 0 ; i < G.vexnum ; ++i){
    134. if(c == G.vexs[i])
    135. break;
    136. }
    137. cout << endl;
    138. while(i >= G.vexnum){
    139. cout << "该点不存在,请重新输入!" << endl;
    140. cout << "请输入遍历连通图的起始点:";
    141. cin >> c;
    142. for(i = 0 ; i < G.vexnum ; ++i){
    143. if(c == G.vexs[i])
    144. break;
    145. }
    146. }
    147. while (true){
    148. int choice=0;
    149. cout<<"请选择搜索策略:1.深度优先搜索 2.广度优先搜索"<<endl;
    150. cin>>choice;
    151. switch (choice) {
    152. case 1:
    153. cout << "深度优先搜索遍历无向图G结果:" << endl;
    154. DFS(G, i);
    155. cout << endl;
    156. break;
    157. case 2:
    158. cout << "广度优先搜索遍历无向图G结果:" << endl;
    159. BFS(G , i);
    160. cout <<endl;
    161. break;
    162. case 0:
    163. cout<<"退出程序"<<endl;
    164. break;
    165. default:
    166. cout<<"输入错误,重新输入"<<endl;
    167. break;
    168. }
    169. break;
    170. }
    171. return 0;
    172. }//main