数据结构:第六章学习小结
思维导图

算法小结
1. 邻接矩阵存储
#define MVNum 100 //最大顶点数
typedef char VerTexType;//假设顶点的数据类型为字符型
typedef int ArcType;//假设边的权值类型为整型
typedef struct
{
VerTexType vexs [MVNum] ;//顶点表
ArcType arcs[MVNum][MVNum];//邻接矩阵
int vexnum, arcnum;//图的当前总顶点数和总边数
)AMGraph;基于邻接矩阵的存储结构
2. 邻接表存储
#define MVNum 100//最大顶点数
typedef char VerTexType;//假设顶点的数据类型为字符型
typedef int ArcType;//假设边的权值类型为整型
typedef struct ArcNode//边结点
{
int adjvex;//邻接点的位置
struct ArcNode *nextarc;//指向下一条边的指针
Otherinfo info;///和边相关的信息
}ArcNode;
typedef struct VNode//顶点
{
VerTexType data;
ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];//AdjList表示邻接表类型
typedef struct//邻接表
{
AdjList vertices;//存储顶点信息的数组
int vexnum,arcnum;//图的当前总顶点数和总边数
}ALGraph;基于邻接表的存储结构
3. DFS算法
void DFS_AM(AMGraph G, int v)
{
visited[v] = true;//访问过的顶点置为true
for(w=0; w<G.vexnum; w++)//依次检查邻接矩阵所在的行
if(G.arcs[v][w]!=0 && !visited[w]) //如果w是v的邻接点且w未访问
DFS_AM(G,w); //递归调用DFS_AM
}基于邻接矩阵的DFS算法
void DFS_AL(ALGraph G, int v)
{
visited[v] = true;//访问过的顶点置为true
p = G.vertices[v].firstarc;//p指向v的边链表的第一个边结点
while(p!=NULL) //边结点不为空
{
w = p->adjvex; //w是v的邻接点
if(!visited[w]) //如果w未访问
DFS_AL(G, w);//递归调用DFS_AL
p = p->nextarc; //p指向下一个边结点
}
}基于邻接表的DFS算法
4. BFS算法
#include<queue>
void BFS(Graph G, int v)
{
visited[v] = true;//访问过的顶点置为true
queue<int> q;//辅助队列Q初始化
q.push(v);//v进队
while(!q.empty())//队列非空
{
int u = q.front();//队头元素出队并置为u
q.pop();
for(int w = 0; w<G.vexnum; w++)
{
if(!visited[w] && G.arcs[u][w]==1)
{//w为u尚未访问的邻接顶点
visited[w] = true;
q.push(w)//w进队
}
}
}
}基于邻接矩阵的BFS算法
#include<queue>
void BFS(Graph G, int v)
{
visited[v] = true;//访问过的顶点置为true
queue<int> q;//辅助队列Q初始化
q.push(v);//v进队
while(!q.empty())//队列非空
{
int u = q.front();//队头元素出队并置为u
q.pop();
p = G.vertices[u].firstarc;//p指向u的第一个边结点
while(p != NULL) //边结点非空
{
w = p->adjvex;
if(!visited[w])//若w未访问
{
visited[w] = true;
q.push(w)//w进队
}
p = p->nextarc; //p指向下一个边结点
}
}
}基于邻接表的BFS算法
5.(补充)非联通图的遍历
//非连通图需遍历所有的连通分量,因此另需一个遍历函数
void Traverse(Graph G)
{
for(v=0; v<G.vexnum; v++)
visited[v] = false;//初始化visit数组(可以直接初始化或menset()函数)
for (v=0;v<G.vexnum;v++){
if(!visited[v])
DFS(G,v);//对尚未访问的顶点调用DFS算法
}
}非连通图的遍历算法
其他知识点小结
1. 使用邻接表存储无向图,为什么要足够稀疏才合算?
答:因为邻接表储存无向图的时候,有n个顶点就要创建n个链表,且每个链表都会存和本顶点相关联的顶点,故每一条边会被存两次,且每一个结点至少会有两个域存储数据。
2. 使用邻接矩阵a存储无向网络,若vi与vj之间不存在边,则a[i][j]值为多少?
答:若权值为正整数,可设为0或负数。若权值为整数,则可设为一个大于所有边权值的数。
3. 最小生成树不一定唯一,但是用算法来查找的最小生成树一般是唯一的(排除使用随机数计算的情况)
4. 重置visit[]数组(用于判断顶点是否被访问)
① for循环重置
②?memset函数重置(更简洁)
//适用于初始化、重新赋值以及清空等情况 //memset()函数在头文件string.h里 #include<string.h> int visit[100]; menset(visit, 0, sizeof(visit));//第一个参数是数组名,第二个参数是设置的值,第三个参数是数组长度
menset()函数
心得体会
1.图需要学习的基本术语较多,但可以大致了解一些比较重要的术语,对于其他的可以接触到再学以致用;
2.另外由于图定义时涉及到的成员变量较多,做题目的时候经常要对照着书本或者前面的代码确认是否写正确_(:з)∠)_;
3. 总体来说,目前对于图的应用的算法基本理解,但自己复现起来可能会生疏,此外感觉自己对于邻接矩阵的上手熟练程度远超于邻接表,可能对于链表的写法不够熟练....之后应该多回顾一下。