第六章学习了图的有关存储结构和遍历,图一个区别于线性表和树结构的又一大数据结构,一个图就是一些顶点的集合,这些顶点通过一系列边连接,边可以有权重,图的应用很广泛,我们可以用图表示路线,表示流程等,所以我们在创建图的过程中需要考虑清楚图的存储结构。
一、图的存储结构:
邻接矩阵定义:
typedef struct { VertexType vexs[MAXVEX]; //顶点表:用来存放顶点与下标的关系 ArcType arc[MAXVEX][MAXVEX]; //邻接矩阵:需要初始化 int vexnum,arcnum; //定点的个数和边的个数 }AMGraph;
邻接表:
与边相关的:
typedef struct ArcNode{ int adjvex; // 邻接点域,该顶点对应的下标 EdgeType weight;//权重 struct ArcNode next; // 链,指向下一个邻接点 }ArcNode;
与顶点相关的:
typedef struct VNode{ // 顶点表结点 VertexType data; //节点名字 ArceNode firstedge; }VNode;
对整张图而言的:
typedef struct{ VertexNode adjList[MAXVEX]; // 邻接表是一个结构体数组,数组中的元素是Vertex节点 int vexnum,arcnum; //图中当前顶点和边数 }ALGraph;
二、图的遍历:列出连通集
图的遍历包括深度优先搜索和广度优先搜索。
在注作业中这道题要求用DFS和BFS列出图的连通集,在本题中,因为元素个数较少,我将图用邻接矩阵存储,书写代码较方便。
深搜遍历类似于树的先序遍历,同样也运用了递归:
广搜与图的存储结构无关,类似树的层次遍历,利用栈来进行横向搜索:
void DFS(int i){//从第0个顶点深搜图 int j; cout<<i<<" ";//访问第i个顶点 vi1[i]=true; for(int j=0;j<vexnum;++j) if((arcs[i][j]==1)&&(!vi1[j])) DFS(j);//递归访问与i相接的结点 }
void BFS(int i){//从第i个顶点广搜图 queue<int> Q; Q.push(i); vi2[i]=true; while(!Q.empty()) { int t=Q.front(); cout<<t<<" ";//输出队头元素 Q.pop(); for(int j=0;j<vexnum;++j){ if(!vi2[j]&&arcs[t][j]==1){ vi2[j]=true; Q.push(j); } } } }
在本题中,用到了两个标记数组vi1和vi2,分别用来判断DFS和BFS中结点是否已被遍历,如果只用一个标记数组会导致深搜完之后,VI数组全部为true,广搜无法进行,这是这道题的易错点之一,我一直卡住这个地方,最后只能求助于博客园,像其学习。
三.最小生成树算法
最小生成树在我们生活中应用十分广泛,可以解决城市路线规划问题,生产流程问题等等,跟着老师学习,比较清楚地学习普里姆算法和克鲁斯卡算法,了解这两种算法的思想,并能根据这种思想画出二叉树,但要真正理解其中的一步步流程及判断各种是否生成边的条件还需要深入思考。这一章对于点和边的定义较多,离开书本还是很难写出代码,希望能在不断练习中掌握。
反思:在老师交代的限时作业中,还是很难顺利下手,得跟着老师的步骤一步一步地来,才能完成好作业,我觉得这应该还是对老师讲的内容没有完全搞懂:
老师的题目里经常有坑,我已经踩了好几次,这些坑是需要非常注意的,需要重视。