第一步:定义邻接表的储存方式(结构体):

data 那边放的是顶点集合
右边放的是边的集合,其实也是点,只不过,两个点就可以看成一个边了是吧,比如第一行,左边表示 v0这个点,,右边就表示 v0 和 v1所构成的边, v0 和 v3点 所构成的边,
边的结构体:
#include<bits/stdc++.h>
#define MVNum 20 //最大顶点数
using namespace std;
const int maxn = 100;
bool visted[maxn];
int topu[maxn];
typedef struct ArcNode{
int adjvex; // 该边所指向顶点的位置
struct ArcNode *nextarc; // 指向下一条边的指针
int info; // 和边相关的信息
}ArcNode;点的结构体:
typedef struct VNode{ // 顶点信息
int data;
int indegree; // 入度
int falg; // 序号
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode , AdjList[MVNum]; 图的结构体:
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 图的当前顶点数和边数
}ALGraph;前面不理解先别往下看
第二步:创建图:
int LocateVex(ALGraph &G, VNode v,int flag){
int cnt = -1;
for (int i= 0;i < G.vexnum ;i++){
if(v.data == G.vertices[i].data && flag == G.vertices[i].falg){
cnt = i;
break;
}
}
return cnt;
}
void CreateHDG (ALGraph &G){
VNode v1, v2;
int flag1,flag2;
cout << "请输入有向连通图的总顶点数和总边数:"<< endl;
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
for (int i= 0;i < G.vexnum ; i++ ){ //输入各点,构造表头节点表
cout << "请输入当前所创建顶点的值" << endl;
cin >> G.vertices[i].data; // 输入顶点值
G.vertices[i].firstarc = NULL; // 初始化表头节点的指针域为NULL
G.vertices[i].indegree = 0;
G.vertices[i].falg = i+1;
}
for (int k = 0 ; k < G.arcnum ; k++){ // 输入各边,构造邻接表
cout << "请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)"<<endl;
cin >> v1.data >> flag1 >> v2.data >> flag2; // 输入一条边依附的两个顶点,和标志,防止两个顶点有相同值的情况,下面的locate函数不起作用
int i =LocateVex(G, v1,flag1) ,j = LocateVex(G, v2,flag2);
G.vertices[j].indegree++;
// cout << i << " "<< j << endl;
//确定v1和v2在G中的位置,即顶点在G.vertices中的序号
ArcNode *p1 = new ArcNode; // 生成一个新的边节点*p1
p1->adjvex = j; // 临界点序号为j
p1->nextarc = G.vertices[i] .firstarc;
G.vertices[i].firstarc = p1;
// 将新节点*p1,插入到顶点vj的边表头部
}
}第三步: DFS:
注意,因为这个dfs没有回朔,所以只能遍历连通图
void DfS(ALGraph G, int v){
cout << G.vertices[v].data<<" ";
visted[v] = true;
ArcNode *p = G.vertices[v] .firstarc;
while(p!=NULL){
int w = p->adjvex;
if(!visted[w]) DfS(G, w);
p = p -> nextarc;
}
}第四步:BFS :
void NextAdjVex(ALGraph G , int u, int &w){
ArcNode *p = G.vertices[u].firstarc;
int flag =0;
while(p!=NULL){
w = p ->adjvex;
if(!visted[w]) {
flag = 1;
break;
}
p = p->nextarc;
}
if(flag == 0) w = -1;
}
queue<int> qu; // 定义一个对列,c++ stl 内置了队列的数据结构,直接拿来用
void Bfs(ALGraph G, int v){
cout << G.vertices[v].data<<" ";
visted[v] = true;
qu.push(v);
while(!qu.empty()){
int u =qu.front();
qu.pop();
ArcNode *p = G.vertices[u].firstarc;
int w;
if(!p){
w = -1;
}
else w = p ->adjvex;
for( ; w >= 0 ;NextAdjVex(G, u, w) )
if(!visted[w]){
cout<< G.vertices[w].data <<" ";
visted[w] = true;
qu.push(w);
}
}
}第五步:计算某个顶点的度:
int CountDegree(ALGraph G,int v){
int cnt = 0;
ArcNode *p = G.vertices[v].firstarc;
while(p != NULL){
cnt ++;
p = p->nextarc;
}
return cnt;
}第六步:拓扑排序:
bool TUPUSort(ALGraph G){
stack<int >s;
for(int i=0;i < G.vexnum ;i++){
if(!G.vertices[i].indegree) s.push(i);
}
int cnt =0;
while(!s.empty()){
int i = s.top();
s.pop();
topu[cnt] = i;
++cnt;
ArcNode *p = G.vertices[i].firstarc;
while(p!=NULL){
int k = p->adjvex;
--G.vertices[k].indegree;
if( G.vertices[k].indegree== 0) s.push(k);
p = p->nextarc;
}
}
if(cnt < G.vexnum) return false;
else return true;
}完工
完整代码
//
// main.cpp
// 第六次实验
//
// Created by 宋玉良 on 2020/12/2.
//
#include<bits/stdc++.h>
#define MVNum 20 //最大顶点数
using namespace std;
const int maxn = 100;
bool visted[maxn];
int topu[maxn];
int cntt = 0,cnt1 = 0;
typedef struct ArcNode{
int adjvex; // 该边所指向顶点的位置
struct ArcNode *nextarc; // 指向下一条边的指针
int info; // 和边相关的信息
}ArcNode;
typedef struct VNode{ // 顶点信息
int data;
int indegree;
int falg;
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode , AdjList[MVNum]; //AdjList 表示邻接表类型
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 图的当前顶点数和边数
}ALGraph;
int LocateVex(ALGraph &G, VNode v,int flag){
int cnt = -1;
for (int i= 0;i < G.vexnum ;i++){
if(v.data == G.vertices[i].data && flag == G.vertices[i].falg){
cnt = i;
break;
}
}
return cnt;
}
void CreateHDG (ALGraph &G){
VNode v1, v2;
int flag1,flag2;
cout << "请输入有向连通图的总顶点数和总边数:"<< endl;
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
for (int i= 0;i < G.vexnum ; i++ ){ //输入各点,构造表头节点表
cout << "请输入当前所创建顶点的值" << endl;
cin >> G.vertices[i].data; // 输入顶点值
G.vertices[i].firstarc = NULL; // 初始化表头节点的指针域为NULL
G.vertices[i].indegree = 0;
G.vertices[i].falg = i+1;
}
for (int k = 0 ; k < G.arcnum ; k++){ // 输入各边,构造邻接表
cout << "请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)"<<endl;
cin >> v1.data >> flag1 >> v2.data >> flag2; // 输入一条边依附的两个顶点,和标志,防止两个顶点有相同值的情况,下面的locate函数不起作用
int i =LocateVex(G, v1,flag1) ,j = LocateVex(G, v2,flag2);
G.vertices[j].indegree++;
// cout << i << " "<< j << endl;
//确定v1和v2在G中的位置,即顶点在G.vertices中的序号
ArcNode *p1 = new ArcNode; // 生成一个新的边节点*p1
p1->adjvex = j; // 临界点序号为j
p1->nextarc = G.vertices[i] .firstarc;
G.vertices[i].firstarc = p1;
// 将新节点*p1,插入到顶点vj的边表头部
}
}
void DfS(ALGraph G, int v){
cntt ++;
cout << G.vertices[v].data<<" ";
visted[v] = true;
ArcNode *p = G.vertices[v] .firstarc;
while(p!=NULL){
int w = p->adjvex;
if(!visted[w]) DfS(G, w);
p = p -> nextarc;
}
}
void NextAdjVex(ALGraph G , int u, int &w){
ArcNode *p = G.vertices[u].firstarc;
int flag =0;
while(p!=NULL){
w = p ->adjvex;
if(!visted[w]) {
flag = 1;
break;
}
p = p->nextarc;
}
if(flag == 0) w = -1;
}
queue<int> qu; // 定义一个对列,c++ stl 内置了队列的数据结构,直接拿来用
void Bfs(ALGraph G, int v){
cnt1++;
cout << G.vertices[v].data<<" ";
visted[v] = true;
qu.push(v);
while(!qu.empty()){
int u =qu.front();
qu.pop();
ArcNode *p = G.vertices[u].firstarc;
int w;
if(!p){
w = -1;
}
else w = p ->adjvex;
for( ; w >= 0 ;NextAdjVex(G, u, w) )
if(!visted[w]){
cnt1++;
cout<< G.vertices[w].data <<" ";
visted[w] = true;
qu.push(w);
}
}
}
int CountDegree(ALGraph G,int v){
int cnt = 0;
ArcNode *p = G.vertices[v].firstarc;
while(p != NULL){
cnt ++;
p = p->nextarc;
}
return cnt;
}
bool TUPUSort(ALGraph G){
stack<int >s;
for(int i=0;i < G.vexnum ;i++){
if(!G.vertices[i].indegree) s.push(i);
}
int cnt =0;
while(!s.empty()){
int i = s.top();
s.pop();
topu[cnt] = i;
++cnt;
ArcNode *p = G.vertices[i].firstarc;
while(p!=NULL){
int k = p->adjvex;
--G.vertices[k].indegree;
if( G.vertices[k].indegree== 0) s.push(k);
p = p->nextarc;
}
}
if(cnt < G.vexnum) return false;
else return true;
}
int main()
{
ALGraph G;
CreateHDG(G);
memset(visted, false, sizeof(visted));
int v;
cout << "请输入遍历开始点的序号:"<<endl;
cin >> v;
cout << "深度优先遍历序列为:" <<endl;
DfS(G, v-1);
cout << endl;
if(cntt < G.vexnum){
cout <<"请从未遍历过的顶点开始遍历"<< endl;
int v1;
cout << "请输入遍历开始点的序号:"<<endl;
cin >> v1;
DfS(G, v1-1);
}
cout << endl;
memset(visted, false, sizeof(visted));
cout << "广度优先遍历序列为: "<< endl;
Bfs(G, v-1);
cout << endl;
if(cnt1 < G.vexnum){
cout <<"请从未遍历过的顶点开始遍历"<< endl;
int v2;
cout << "请输入遍历开始点的序号:"<<endl;
cin >> v2;
Bfs(G, v2-1);
}
cout << endl;
if(TUPUSort(G)){
cout << "拓扑排序成功,拓扑序列为:"<<endl;
for(int i = 0; i<G.vexnum ;i++){
cout << topu[i]<<" ";
}
}
else{
cout << "此图无法构成拓扑序列";
}
cout << endl;
}
//7 10
//0 1 2 3 4 5 6
//0 2
//0 4
//1 2
//1 3
//2 5
//3 5
//2 4
//2 6
//5 6
//4 6
//0
/*输入样例和输出样例:
请输入有向连通图的总顶点数和总边数:
4 4
请输入当前所创建顶点的值
2
请输入当前所创建顶点的值
3
请输入当前所创建顶点的值
5
请输入当前所创建顶点的值
4
请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)
2 1
3 2
请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)
2 1 5 3
请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)
5 3 4 4
请分别输入当前所创建边所连接的两个顶点的值和序号(请输入四个数)
4 4 2 1
请输入遍历开始点的序号:
0
深度优先遍历序列为:
2 5 4 3
2 5 3 4
此图无法构成拓扑序列
*/

京公网安备 11010502036488号