数据结构学习第二十三课(图)

图:

1 数据:顶点
2 关系:边
3 根据边是否有方向:有向图,无向图
4 图的描述:
邻接矩阵:一个一维数组保存顶点,二维数组保存边
邻接表:一个一维数组保存顶点(链表头结点),链表保存顶点能到达的边
5 网图:
边不仅仅描述顶点之间的关联,还表达(代价,权重)等;

1 源文件

//邻接矩阵描述图
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
#define Vertexs 6
#define Edges 7
struct Graph
{
	int vertexs;//顶点个数
	int edges;//边数
	char* pVertex;//指向保存所有顶点的一维数组的指针
	int** pEdge;//指向保存所有边的二维数组的指针
};
//创建图对象
struct Graph* createGraph();
//初始化图对象
void initGraph(struct Graph* g, int vertexs, int edges,
	char* v, int map[Vertexs][Vertexs]);
//显示
void show(struct Graph* g);
//获取下标
int getIdx(char* v, int vertexs, char c);
//遍历
void travel(struct Graph* g, char beg);
//深度优先遍历
void DFS(struct Graph* g, char beg, bool isFind[Vertexs]);
//广度优先遍历
void BFS(struct Graph* g, char beg, bool isFind[Vertexs]);
//找途中某个地点的第一个相邻顶点,找到返回下标,没找到返回-1
int findFirstVertex(struct Graph*g,int beg, bool isFind[Vertexs]);
//找途中某个地点的下一个相邻顶点,找到返回下标,没找到返回-1
int findNextVertex(struct Graph* g, int beg, bool isFind[Vertexs]);
int main()
{
	char buff[7] = "ABCDEF";
	int map[Vertexs][Vertexs] =
	{
		{0,1,1,0,0,0},
		{1,0,0,1,0,0},
		{1,0,0,1,1,1},
		{0,1,1,0,0,0},
		{0,0,1,0,0,1},
		{0,0,1,0,1,0}

	};
	struct Graph* g = createGraph();
	initGraph(g, 6, 7, buff, map);
	show(g);
	travel(g, 'A');

	return 0;
}

Graph* createGraph()
{
	struct Graph* g = new Graph;
	if (nullptr == g)
	{
		return nullptr;
	}
	memset(g, 0, sizeof(Graph));
	return g;
}

void initGraph(Graph* g, int vertexs, int edges, char* v, int map[Vertexs][Vertexs])
{
	//顶点个数,边数赋值
	g->vertexs = vertexs;
	g->edges = edges;
	//开内存
	g->pVertex = new char[g->vertexs];
	memcpy(g->pVertex, v, sizeof(char) * g->vertexs);
	//开内存保存指针变量
	g->pEdge = new int* [g->vertexs];
	//给每个指针变量开内存
	for (int i = 0; i < g->vertexs; i++)
	{
		g->pEdge[i] = new int[g->vertexs]; 
		memcpy(g->pEdge[i], map[i], sizeof(int) * g->vertexs);
	}
}
void show(struct Graph* g)
{
	for (int i = 0; i <= g->vertexs; i++)
	{
		for (int j = 0; j <= g->vertexs; j++)
		{
			if (0 == i && 0 == j)//左上角
			{
				printf("  ");
			}
			else if (0 == i)//最上面一行
			{
				printf("%c ", g->pVertex[j-1]);
			}
			else if (0 == j)//最左边一列
			{
				printf("%c ", g->pVertex[i-1]);
			}
			else//边
			{
				printf("%d ", g->pEdge[i - 1][j - 1]);
			}
		}
		printf("\n");
	}
}
int getIdx(char* v, int vertexs, char c)
{
	for (int i = 0; i < vertexs; i++)
	{
		if (v[i] == c)
		{
			return i;
		}
	}
	return -1;
}
void travel(struct Graph* g, char beg)
{
	bool* isFind = new bool[g->vertexs];
	memset(isFind, 0, sizeof(bool) * g->vertexs);
	printf("BFS:%c ",beg);
	DFS(g, beg, isFind);
	memset(isFind, 0, sizeof(bool) * g->vertexs);
	printf("\nDFS:%c ", beg);
	BFS(g, beg, isFind);
	delete[] isFind;
}
void DFS(Graph* g, char beg, bool isFind[Vertexs])
{
	int curIdx = getIdx(g->pVertex, g->vertexs, beg);
	isFind[curIdx] = true;
	int nextIdx = findFirstVertex(g, curIdx, isFind);
	while (1)
	{
		if (-1 == nextIdx)
			break;
		if (!isFind[nextIdx])
		{
			printf("%c ", g->pVertex[nextIdx]);
			DFS(g, g->pVertex[nextIdx], isFind);
		}
		nextIdx=findNextVertex(g, curIdx, isFind);
	}
}
void BFS(Graph* g, char beg, bool isFind[Vertexs])
{
	queue<int> q;//队列
	//把第一个放到队列中
	q.push(getIdx(g->pVertex, g->vertexs, beg));
	isFind[getIdx(g->pVertex, g->vertexs, beg)] = true;
	int headIdx;
	int idx;
	while (!q.empty())
	{
		headIdx = q.front();
		//删掉队列头
		q.pop();
		idx = findFirstVertex(g, headIdx, isFind);
		//循环找当前队列头的声音相邻顶点并放到队列中,放完了就结束
		while (1)
		{
			if (idx == -1)break;
			if (!isFind[idx])
			{
				isFind[idx] = true;
				printf("%c ", g->pVertex[idx]);
				q.push(idx);
			}
			idx = findNextVertex(g, headIdx, isFind);
		}
 	}
}
int findFirstVertex(Graph* g, int beg, bool isFind[Vertexs])
{
	for (int i = 0; i < g->vertexs; i++)
	{
		if (isFind[i])
			continue;
		if (1 == g->pEdge[beg][i])
			return i;
	}
	return -1;
}
int findNextVertex(Graph* g, int beg, bool isFind[Vertexs])
{
	for (int i = beg+1; i < g->vertexs; i++)
	{
		if (isFind[i])
			continue;
		if (1 == g->pEdge[beg][i])
			return i;
	}
	return -1;
}

2,两种遍历思想

深度优先遍历:Deep First Search DFS
思想:
找第一个,
循环找下一个一直到找不到下一个,
循环结束.

广度优先遍历:Breadth First Search BFS
思想:
先把起点放到队列中,
循环找起点的所有相邻顶点都放到队列中,
所有相邻顶点都放完了,
就删掉队列头,
然后循环找当前队列头的所有相邻顶点,
并放到队列中去;

猜你喜欢

转载自blog.csdn.net/kdnnnd/article/details/120244934