目录
定义无向图邻接表
#define MVnum 100 //最大定点数
//边(弧)的结点结构定义
struct ArcNode
{
int adjvex; //该边所指向的顶点的位置
ArcNode* nextarc; //指向下一条边的指针
};
//顶点的结点结构定义
struct VexNode
{
string data; //顶点信息
ArcNode* fristarc; //指向第一条依附该顶点的边的指针
};
//图的结构定义
struct ALGraph
{
VexNode vertices[MVnum]; //邻接表数组
int vexnum, arcnum; //图的当前总顶点数和总边数
};
构造无向图
(1)输入总顶点数和总边数。
(2)建立顶点表
依次输入点的信息存入顶点表中
使每个表头结点的指针域初始化为NULL
(3)创建邻接表
依次输入每条边依附的两个顶点
确定两个顶点的序号i和j,建立边结点
将此边结点分别插入到vi和vj,对应的两个边链表的头部
//声明
int LocateVex(ALGraph G, string u);
//采用邻接表构建无向图
bool CreateUDG(ALGraph& G)
{
//1.输入总顶点数和总边数
cout << "请输入顶点数:" << endl;
cin >> G.vexnum;
cout << "请输入边数:" << endl;
cin >> G.arcnum;
//2.建立顶点表
cout << "请输入顶点信息:" << endl;
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].fristarc = NULL; //初始化表头结点的指针域
}
//3.创建邻接表
cout << "请输入一条边所依附的两个顶点:" << endl;
for (int k = 0; k < G.arcnum; k++)
{
string v1, v2;
cin >> v1 >> v2; //输入一条边所依附的两个顶点
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
ArcNode* p1 = new ArcNode; //生成新的边结点
p1->adjvex = j; //邻接点序号为j
p1->nextarc = G.vertices[i].fristarc;
G.vertices[i].fristarc = p1; //将新结点p1插入顶点vi的边表头部
ArcNode* p2 = new ArcNode; //生成另一个对称的新的边结点
p2->adjvex = i; //邻接点序号为i
p2->nextarc = G.vertices[j].fristarc;
G.vertices[j].fristarc = p2; //将新结点p2插入顶点vj的边表头部
}
return true;
}
//在图G中查找顶点u,存在返回顶点表中的下标,否则返回-1
int LocateVex(ALGraph G, string u)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.vertices[i].data == u)
{
return i;
}
}
return -1;
}
打印邻接表
//打印
void PrintVex(ALGraph G)
{
for (int i = 0; i < G.vexnum; i++)
{
cout << G.vertices[i].data << ": ";
while (G.vertices[i].fristarc)
{
cout << G.vertices[i].fristarc->adjvex<<" ";
G.vertices[i].fristarc = G.vertices[i].fristarc->nextarc;
}
cout << endl;
}
}
无向图邻接表深度优先遍历(DFS)
1、在访问图中某一起始顶点v后,由v出发,访问它的任一邻接顶点w1;
2、再从w1出发,访问与w1邻接但还未被访问过的顶点w2;
3、然后再从w2出发,进行类似的访问,...
4、如此进行下去,直至到达所有的邻接顶点都被访问过的顶点u为止。接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。
5、如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;
6、如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。
bool visited[MVnum]; //深度优先访问标志数组,初始为false;
//无向图邻接表深度优先遍历
void DFS(ALGraph G, int v)
{
//访问第v个顶点,并置访问标志数组为true
cout << G.vertices[v].data << " ";
visited[v] = true;
ArcNode *p = G.vertices[v].fristarc; //p指向v的边链表的第一个边结点
while (p)//边结点非空
{
int w = p->adjvex;//表示w是v的邻接点
if (!visited[w]) //如果w为访问,则递归调用DFS
{
DFS(G, w);
}
p = p->nextarc; //p指向下一边结点
}
}
无向图邻接表广度优先遍历(BFS)
1、从图的一结点出发,首先依次访问该结点的所有邻接结点v1,v2......vn再按这些顶点被访问的先后次序依次访问与它们相邻的所有未被访问的顶点。
2、重复此过程,直至所有顶点均被访问为止。
bool visited1[MVnum]; //广度优先访问标志数组,初始为false;
//无向图邻接表广度优先遍历
void BFS(ALGraph G, int v)
{
//访问第v个顶点,并置访问标志数组为true
cout << G.vertices[v].data << " ";
visited1[v] = true;
queue<int>Q; //创建队列Q
Q.push(v); //v进队
while (!Q.empty()) //队列非空
{
int p = Q.front(); //将队头元素赋给p
Q.pop(); //删除队顶元素
ArcNode* arc = G.vertices[p].fristarc; //arc指向p的边链表的第一个边结点
while (arc) //边结点非空
{
if (!visited1[arc->adjvex]) //判断边结点arc中指向顶点的位置是否被访问
{
cout << G.vertices[arc->adjvex].data << " ";//输出边结点arc记录位置的顶点值
visited1[arc->adjvex] = true; //标记为true
Q.push(arc->adjvex); //边结点arc指向顶点中的位置入队
}
arc = arc->nextarc; //arc指向下一边结点
}
}
}
测试
int main()
{
ALGraph G;
CreateUDG(G); //构造无向图邻接表
cout << "图G的邻接表为:" << endl;
PrintVex(G); //打印邻接表
int v = 0;
cout << "深度优先遍历为:" << endl;
DFS(G, v);
cout << endl;
cout << "广度优先遍历为:" << endl;
BFS(G, v);
cout << endl;
system("pause");
return 0;
}
完整代码
#include<iostream>
using namespace std;
#include<queue>
#define MVnum 100 //最大定点数
//边(弧)的结点结构定义
struct ArcNode
{
int adjvex; //该边所指向的顶点的位置
ArcNode* nextarc; //指向下一条边的指针
};
//顶点的结点结构定义
struct VexNode
{
string data; //顶点信息
ArcNode* fristarc; //指向第一条依附该顶点的边的指针
};
//图的结构定义
struct ALGraph
{
VexNode vertices[MVnum]; //邻接表数组
int vexnum, arcnum; //图的当前总顶点数和总边数
};
bool visited[MVnum]; //深度优先访问标志数组,初始为false;
bool visited1[MVnum]; //广度优先访问标志数组,初始为false;
//声明
int LocateVex(ALGraph G, string u);
//采用邻接表构建无向图
bool CreateUDG(ALGraph& G)
{
//1.输入总顶点数和总边数
cout << "请输入顶点数:" << endl;
cin >> G.vexnum;
cout << "请输入边数:" << endl;
cin >> G.arcnum;
//2.建立顶点表
cout << "请输入顶点信息:" << endl;
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].fristarc = NULL; //初始化表头结点的指针域
}
//3.创建邻接表
cout << "请输入一条边所依附的两个顶点:" << endl;
for (int k = 0; k < G.arcnum; k++)
{
string v1, v2;
cin >> v1 >> v2; //输入一条边所依附的两个顶点
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
ArcNode* p1 = new ArcNode; //生成新的边结点
p1->adjvex = j; //邻接点序号为j
p1->nextarc = G.vertices[i].fristarc;
G.vertices[i].fristarc = p1; //将新结点p1插入顶点vi的边表头部
ArcNode* p2 = new ArcNode; //生成另一个对称的新的边结点
p2->adjvex = i; //邻接点序号为i
p2->nextarc = G.vertices[j].fristarc;
G.vertices[j].fristarc = p2; //将新结点p2插入顶点vj的边表头部
}
return true;
}
//在图G中查找顶点u,存在返回顶点表中的下标,否则返回-1
int LocateVex(ALGraph G, string u)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.vertices[i].data == u)
{
return i;
}
}
return -1;
}
//打印
void PrintVex(ALGraph G)
{
for (int i = 0; i < G.vexnum; i++)
{
cout << G.vertices[i].data << ": ";
while (G.vertices[i].fristarc)
{
cout << G.vertices[i].fristarc->adjvex<<" ";
G.vertices[i].fristarc = G.vertices[i].fristarc->nextarc;
}
cout << endl;
}
}
//无向图邻接表深度优先遍历
void DFS(ALGraph G, int v)
{
//访问第v个顶点,并置访问标志数组为true
cout << G.vertices[v].data << " ";
visited[v] = true;
ArcNode *p = G.vertices[v].fristarc; //p指向v的边链表的第一个边结点
while (p)//边结点非空
{
int w = p->adjvex;//表示w是v的邻接点
if (!visited[w]) //如果w为访问,则递归调用DFS
{
DFS(G, w);
}
p = p->nextarc; //p指向下一边结点
}
}
//无向图邻接表广度优先遍历
void BFS(ALGraph G, int v)
{
//访问第v个顶点,并置访问标志数组为true
cout << G.vertices[v].data << " ";
visited1[v] = true;
queue<int>Q; //创建队列Q
Q.push(v); //v进队
while (!Q.empty()) //队列非空
{
int p = Q.front(); //将队头元素赋给p
Q.pop(); //删除队顶元素
ArcNode* arc = G.vertices[p].fristarc; //arc指向p的边链表的第一个边结点
while (arc) //边结点非空
{
if (!visited1[arc->adjvex]) //判断边结点arc中指向顶点的位置是否被访问
{
cout << G.vertices[arc->adjvex].data << " ";//输出边结点arc记录位置的顶点值
visited1[arc->adjvex] = true; //标记为true
Q.push(arc->adjvex); //边结点arc指向顶点中的位置入队
}
arc = arc->nextarc; //arc指向下一边结点
}
}
}
int main()
{
ALGraph G;
CreateUDG(G); //构造无向图邻接表
cout << "图G的邻接表为:" << endl;
PrintVex(G); //打印邻接表
int v = 0;
cout << "深度优先遍历为:" << endl;
DFS(G, v);
cout << endl;
cout << "广度优先遍历为:" << endl;
BFS(G, v);
cout << endl;
system("pause");
return 0;
}