目录
一、基本概念
1.多对多的数据结构 - 图
2.构成:
顶点 vertexs
边: 用来描述顶点之间的关系 edges
3.描述图的方式:临接表:链表
临接矩阵:数组4.网图:边有长度(权值)
A星寻路算法:
f = g + h
f = g + h + w其中的w就是可能的权值5.图的遍历:
深度优先遍历:Deap First Search
一路往下遍历,没有了再换周围其他节点
广度优先遍历:Breadth First Search
先把周围的遍历完,然后再往下搜索关键实现函数:
找某个顶点的第一个相邻顶点
找某个顶点的第二个相邻顶点
二、代码实现:
注:这里的DFS采用递归的方法实现.
①代码的框架
include <iostream> #include <stdio.h> #include <queue> using namespace std; //临界矩阵描述图 #define VERTEXS 6 #define EDGES 7 //图类型 struct Graph { int vertexs; //顶点个数 int edges; //边条数 char* pVertex; //指向 存储所有顶点的一维数组 int** pEdge; //二级指针 描述矩阵 }; //创建图对象 Graph* createGraph(); //初始化图对象 void initGraph(Graph* g, int vertexs, int edges, char* v, int map[VERTEXS][VERTEXS]); //显示图对象 void showGraph(Graph* g); //从图中找到参数顶点在顶点数组中的下标并返回 int _getIndex(Graph* g, char c); //找beg参数对应顶点的第一个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过 int findFirstVertex(Graph* g, int beg, bool isFind[VERTEXS]); //找beg参数对应顶点的第二个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过 int findNextVertex(Graph* g, int beg, bool isFind[VERTEXS]); void DFS(Graph* g, char beg, bool isFind[VERTEXS]); void BFS(Graph* g, char beg, bool isFind[VERTEXS]); void travel(Graph* g, char beg,bool isD=true) { bool isFind[VERTEXS] = { 0 }; if (isD) { printf("深度优先遍历:%c ", beg); DFS(g, beg, isFind); printf("\n"); } else { printf("广度优先遍历:%c ", beg); BFS(g, beg, isFind); printf("\n"); } } int main() { Graph* g = createGraph(); char buff[7] = "ABCDEF"; int map[VERTEXS][VERTEXS] = { { 0, 1, 0, 1, 0, 0 }, { 1, 0, 1, 0, 0, 0 }, { 0, 1, 0, 1, 1, 1 }, { 1, 0, 1, 0, 0, 1 }, { 0, 0, 1, 0, 0, 0 }, { 0, 0, 1, 1, 0, 0 } }; initGraph(g, VERTEXS, EDGES, buff, map); showGraph(g); // travel(g, 'A'); travel(g, 'A',1); while (1); return 0; }
②初始化、创建、show函数的实现
//创建图对象 Graph* createGraph() { Graph* pNew = new Graph; if (NULL == pNew) return NULL; memset(pNew, 0, sizeof(Graph)); return pNew; } //初始化图对象 void initGraph(Graph* g, int vertexs, int edges, char* v, int map[VERTEXS][VERTEXS]) { #if 1 //1 开内存 g->vertexs = vertexs; g->edges = edges; g->pVertex = new char[g->vertexs]; g->pEdge = new int*[g->vertexs]; for (int i = 0; i < g->vertexs; i++) { g->pEdge[i] = new int[g->vertexs]; } //2 数据拷贝 memcpy(g->pVertex, v, sizeof(char)*g->vertexs); for (int i = 0; i < g->vertexs; i++) { memcpy(g->pEdge[i], map[i], sizeof(int)*g->vertexs); } #else //1 开内存 //此处最好也是用户输入 g->vertexs = vertexs; g->edges = edges; g->pVertex = new char[g->vertexs]; g->pEdge = new int*[g->vertexs]; for (int i = 0; i < g->vertexs; i++) { g->pEdge[i] = new int[g->vertexs]; memset(g->pEdge[i], 0, sizeof(int)*g->vertexs); } printf("请输入顶点:"); scanf("%s", g->pVertex);//输入的时候自行把握 不要越界 char buff[5] = { 0 }; char src, dst; int srcIdx, dstIdx; for (int i = 0; i < g->edges; i++) { printf("请输入第%d条边:", i + 1); scanf("%s", buff);// A->B src = buff[0]; dst = buff[3]; srcIdx = _getIndex(g, src); dstIdx = _getIndex(g, dst); g->pEdge[srcIdx][dstIdx] = 1; #if 1 //如果是无向图 加这一行 g->pEdge[dstIdx][srcIdx] = 1; #endif } #endif } //从图中找到参数顶点在顶点数组中的下标并返回 int _getIndex(Graph* g, char c) { for (int i = 0; i < g->vertexs; i++) { if (c == g->pVertex[i]) return i; } return -1; } //显示图对象 void showGraph(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"); } }
③寻找第一个临近节点,寻找第二个临近节点
//找beg参数对应顶点的第一个相邻顶点,找到了返回其下标,没找到返回-1 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; //找到beg对应的那一行,邻接矩阵中遇到的第一个就是第一个相邻的顶点
}
return -1;
}
//找beg参数对应顶点的第二个相邻顶点,找到了返回其下标,没找到返回-1 isFind数组标记有没有找过
int findNextVertex(Graph* g, int beg, bool isFind[VERTEXS])
{
for (int i = beg+1; i < g->vertexs; i++)
{//注:为什么i是从beg+1开始的,是因为用的时候传入的CurrentIdx,也就是第一次找到的下标---->+1就能从后面开始搜
if (isFind[i]) continue;
if (1 == g->pEdge[beg][i]) return i;
}
return -1;
}
④DFS和BFS
//递归实现栈的回退
void DFS(Graph* g, char beg, bool isFind[VERTEXS])
{
//找beg的第一个相邻顶点x ,继续找x的第一个相邻顶点y 直到没有找到 结束
int currentIdx = _getIndex(g,beg);
isFind[currentIdx] = 1;//每递归到一个,就标记一个.
int nextIdx = findFirstVertex(g, currentIdx, isFind);
while (1)
{
if (-1 == nextIdx) break;
if (false == isFind[nextIdx])
{
printf("%c ", g->pVertex[nextIdx]);
DFS(g, g->pVertex[nextIdx],isFind);
}
nextIdx = findNextVertex(g, currentIdx, isFind);
}
}
void BFS(Graph* g, char beg, bool isFind[VERTEXS])
{
queue<int> q;
q.push(_getIndex(g, beg));//把第一个放到队列里
isFind[_getIndex(g, beg)] = true;
int headIdx;
int idx;
while (!q.empty())
{//step1:找出队首的元素,保存并在队列中删除
headIdx = q.front();//队列头 第一个
q.pop();//删掉第一个
//step2:把刚才保存的顶点的相邻的顶点都放到队列中
idx = findFirstVertex(g, headIdx, isFind);//找到头结点的邻接的结点 while 找出全部的.
while (1)
{
if (-1 == idx) break;
if (!isFind[idx])
{
isFind[idx] = true;//每push进去一个,就标记一个
printf("%c ", g->pVertex[idx]);
q.push(idx);
}
idx = findNextVertex(g, headIdx, isFind);
}
}
}