数据结构总结之图

1.起因

为什么要总结图,因为两次华为面试过程中,因为有关图的面试题都回答不上来。

问题一:什么是深度优先什么是广度优先,最短路径使用的是深度优先还是广度优先。

问题二:什么是拓扑排序?怎么实现?

2.图的定义

领接矩阵

typedef struct  
{
	int edges[MaxSize][MaxSize];
	int n, e;//n顶点数,e边数
	int vex[MaxSize];//节点信息,顶点编号
}MGraph;

领接表 

//领接表定义
typedef struct ArcNode
{
	int adjvex;//该边指向的节点位置
	struct ArcNode *nextarc;//指向下一条边的指针
	int info;//该边的相关信息,比如权重
};
typedef struct VNode {
	char data;//顶点信息
	ArcNode *firstarc;//指向第一条边的指针
};
typedef struct AGraph
{
	VNode adjlist[MaxSize];//领接表
	int n, e;//顶点数和边数

};

3.深度优先遍历

首先访问任意一个节点V并标记为已访问,然后选择v的任意一个未被访问的领接点w并访问,继续选择w的任意未被访问的领接点,依次重复。

如果一个节点的所有领接点都已经被访问,依次退回最近访问过的节点,如果该节点有未被访问的领接点则访问,直到所有的节点都被访问。

递归实现

循环实现

4.广度优先遍历

5.最小代价生成树

6.最短路径

7.拓扑排序

7.1拓扑排序

邻接表表头结构进行修改:增加一个count字段,统计顶点当前入度

typedef struct VNode {
	char data;//顶点信息
	ArcNode *firstarc;//指向第一条边的指针
	int count;//记录顶点当前的入度
};

outputNum:记录当前输出的顶点个数,初始化为0.

1.扫描所有顶点,将入度为0的顶点入栈;

2.在栈不为空的情形下执行循环:

   2.1出栈,outputNum+1,输出出栈顶点

   2.2将由该顶点引出边所指向的所有顶点的入度减1,如果入度减为0入栈

3.退出循环后,判断outputNum是否等于图形的顶点数,是1否0 

实现代码

int TopSort(AGraph *g)
{
	int outputNum = 0;//记录已经输出顶点个数
	//1.扫描所有顶点,将入度为0的顶点入栈
	int m_stack[MaxSize], top = -1;
	for (int i = 0; i < g->n;i++)
	{
		if (g->adjlist[i].count==0)
		{
			++top;
			m_stack[top] = i;
		}
	}

	//栈不空时,执行循环
	while (top!=-1)
	{
		//1.顶点出栈
		int i = m_stack[top];
		top--;
		//2.计数加1,输出当前顶点
		++outputNum;
		cout << i << " ";

		//由此顶点引出的边所指向的多有顶点入度都减1,如果入度变为了0的顶点如栈
		ArcNode* p = g->adjlist[i].firstarc;
		while (p!=nullptr)
		{
			int j = p->adjvex;
			--(g->adjlist[j].count);
			if (g->adjlist[j].count==0)
			{
				++top;
				m_stack[top] = j;
			}
			p->nextarc;

		}

	}

	if (outputNum==g->n)
	{
		return 1;
	}

	return 0;
}

7.2逆序拓扑排序,DFS实现

猜你喜欢

转载自blog.csdn.net/haimianjie2012/article/details/112305179