数据结构-图
对于上面这种有向图,现在分别以邻接矩阵、邻接表和十字链表的存储结构实现,并对前两种数据结构使用广度遍历和深度遍历。(在这里我只给出关键代码,详细代码,请通过文末的我的Github代码仓库的链接前往我的代码仓库查看!)
一、首先是以邻接矩阵的方式实现
#define MinInt 0
typedef char VerTexType;
typedef int ArcType;
class GraphLJZ
{
private:
int vexnum, arcnum; //图总顶点数目、总边数目
VerTexType* vexs; //顶点表
ArcType** arcs; //邻接矩阵
bool* visit; //访问标志
void RedeafultVisit();//恢复访问标志表的默认设置
public:
GraphLJZ(int num1, int num2);
void Init();
void Create();
int Print();
int LocateVex(char node);
void BFS(int v);//广度优先搜索遍历图
void DFS(int v);//深度优先搜索遍历图
};
……
//创建有向图的邻接矩阵
void GraphLJZ::Create()
{
int i, k;
for (int j = 0; j < arcnum; j++)
{
char v1, v2;
cout << "请输入起点和终点:";
cin >> v1 >> v2;
i = LocateVex(v1);
k = LocateVex(v2);
int temp;
cout << "请输入该边的权重:";
cin >> temp;
arcs[i][k] = temp;
}
}
//广度优先搜索遍历图
void GraphLJZ::BFS(int num)
{
int temp=0;
Queue q(vexnum);
visit[num] = true;
cout << vexs[num] << " ";
q.Enqueue(num);
while (!q.Empty())
{
int w;
q.GetTop(w);
q.Dequeue(temp);
for(int u=0;u<vexnum;u++)
if (arcs[w][u] != 0 && visit[u] == false)
{
cout << vexs[u] << " ";
q.Enqueue(u);
visit[u] = true;
}
}
cout << endl;
RedeafultVisit();
}
//深度优先搜索遍历图
void GraphLJZ::DFS(int v)
{
cout << vexs[v]<<" ";
visit[v] = true;
for (int w = 0; w < vexnum; w++)
if (arcs[v][w] != 0 && visit[w] == false)
DFS(w);
}
二、以邻接表的形式实现
typedef char VerTexType;
typedef int ArcType;
//边节点
struct ArcNode
{
int adjvex;
ArcNode* nextArc;
int length;
};
//顶点节点
struct VexNode
{
VerTexType data;
ArcNode* theArc;
};
//邻接表类
class GraphLJB
{
private:
VexNode *vertices; //顶点表
int vexNum, arcNum; //顶点数、边数
bool* visit; //访问标志表
void RedeafultVisit();//恢复访问标志表的默认设置
public:
GraphLJB(int node, int line);
void initializeTheVertexTable();
int LocateVex(char node);
void Create();
void Print();
void BFS(int v); //广度优先搜索遍历图
void DFS(int v);//深度优先搜索遍历图
};
……
//创建邻接表
void GraphLJB::Create()
{
for (int k = 0; k < arcNum; k++)
{
char v1, v2;
int i, j;
cout << "请输入起点和终点:";
cin >> v1 >> v2;
i = LocateVex(v1);
j = LocateVex(v2);
ArcNode* next = new ArcNode;
next->adjvex = j;
cout << "请输入该边权重:";
cin >> next->length;
next->nextArc = NULL;
//将边串联
if (vertices[i].theArc == NULL)
{
vertices[i].theArc = next;
}
else
{
ArcNode* p;
p = vertices[i].theArc;
while (p->nextArc) //找到链表的最后一个结点
{
p = p->nextArc;
}
p->nextArc = next;
}
}
}
//广度优先搜索遍历图
void GraphLJB::BFS(int v)
{
int temp;
Queue q(vexNum);
cout << vertices[v].data << " ";
visit[v] = true;
q.Enqueue(v);
while (!q.Empty())
{
int w;
q.GetTop(w);
q.Dequeue(temp);
for (ArcNode* u = vertices[w].theArc; u != NULL; u = u->nextArc)
{
if (visit[u->adjvex] == false)
{
cout << vertices[u->adjvex].data << " ";
q.Enqueue(u->adjvex);
visit[u->adjvex] = true;
}
}
}
cout << endl;
RedeafultVisit();
}
//深度优先搜索遍历图
void GraphLJB::DFS(int v)
{
cout << vertices[v].data << " ";
visit[v] = true;
ArcNode* p = vertices[v].theArc;
while (p != NULL)
{
int w = p->adjvex;
if (visit[w] == false)
DFS(w);
p = p->nextArc;
}
}
三、以十字链表形式实现
typedef char VerTexType;
typedef int ArcType;
//弧节点
struct ArcBox
{
int tailVext, headVext; //该弧的尾和头顶点的位置
ArcBox* hlink, * tlink; //分别为弧头相同和弧尾相同的链域
int length;
};
//顶点节点
struct vexNode
{
VerTexType data;
ArcBox* linein, * lineout; //指向出弧、入弧
};
//十字链表
class GraphSZLB
{
private:
int vexnum, arcnum; //顶点数、边数
vexNode* xlist;
public:
GraphSZLB(int num1, int num2);
void Init();
int LocateVex(char node);
void Create();
void Print();
};
……
void GraphSZLB::Create()
{
for (int k = 0; k < arcnum; k++)
{
char v1, v2;
cout << "请输入起点和终点:";
cin >> v1 >> v2;
int i, j;
i = LocateVex(v1);
j = LocateVex(v2);
ArcBox* next = new ArcBox;
next->headVext = i;
next->tailVext = j;
cout << "输入该边的权重:";
cin >> next->length;
next->hlink = NULL;
next->tlink = NULL;
//该位置的顶点的出度还为空时,直接让 lineout 指针指向新的表结点
//记录出度信息
if (xlist[i].lineout == NULL)
{
xlist[i].lineout = next;
}
else
{
ArcBox* now;
now = xlist[i].lineout;
while (now->tlink)
{
now = now->tlink;
}
now->tlink = next;
}
//记录入度信息
if (xlist[j].linein == NULL)
{
xlist[j].linein = next;
}
else
{
ArcBox* now;
now = xlist[j].linein;
while (now->hlink)
{
now = now->hlink;
}
now->hlink = next;
}
}
}
最后通过主函数调用运行
#include <iostream>
#include "GraphLJZ.h"
#include "GraphLJB.h"
#include "GraphSZLB.h"
using namespace std;
int main()
{
int num1, num2; //图的顶点数,边数
cout << "请输入图的顶点数和边数:";
cin >> num1 >> num2;
cout << "以十字链表构图:" << endl;
GraphSZLB g1(num1, num2);
g1.Init();
g1.Create();
g1.Print();
cout << "============================" << endl;
cout << endl;
cout << "以邻接表构图:" << endl;
GraphLJB g2(num1, num2);
g2.initializeTheVertexTable();
g2.Create();
g2.Print();
cout << "广度优先搜索遍历图:" << endl;
g2.BFS(6);
cout << "深度优先搜索遍历图:" << endl;
g2.DFS(6);
cout << endl;
cout << "======================================" << endl;
cout << endl;
cout << "以邻接矩阵构图:" << endl;
GraphLJZ g3(num1,num2);
g3.Init();
g3.Create();
g3.Print();
cout << "广度优先搜索遍历图:" << endl;
g3.BFS(6);
cout << "深度优先搜索遍历图" << endl;
g3.DFS(6);
cout << endl;
cout << "===========================================" << endl;
cout << endl;
return 0;
}
输出结果如下:
请输入图的顶点数和边数:7 9
以十字链表构图:
请输入顶点信息:A B C D E F G
请输入起点和终点:A B
输入该边的权重:7
请输入起点和终点:A D
输入该边的权重:18
请输入起点和终点:B C
输入该边的权重:2
请输入起点和终点:C F
输入该边的权重:9
请输入起点和终点:D E
输入该边的权重:20
请输入起点和终点:F D
输入该边的权重:3
请输入起点和终点:G A
输入该边的权重:14
请输入起点和终点:G C
输入该边的权重:6
请输入起点和终点:G F
输入该边的权重:4
各个顶点的出度信息:
A->B:7 A->D:18 ^
B->C:2 ^
C->F:9 ^
D->E:20 ^
^
F->D:3 ^
G->A:14 G->C:6 G->F:4 ^
各个顶点的入度信息:
A<-G:14 ^
B<-A:7 ^
C<-B:2 C<-G:6 ^
D<-A:18 D<-F:3 ^
E<-D:20 ^
F<-C:9 F<-G:4 ^
^
============================
以邻接表构图:
请输入顶点信息:A B C D E F G
请输入起点和终点:A B
请输入该边权重:7
请输入起点和终点:A D
请输入该边权重:18
请输入起点和终点:B C
请输入该边权重:2
请输入起点和终点:C F
请输入该边权重:9
请输入起点和终点:D E
请输入该边权重:20
请输入起点和终点:F D
请输入该边权重:3
请输入起点和终点:G A
请输入该边权重:14
请输入起点和终点:G C
请输入该边权重:6
请输入起点和终点:G F
请输入该边权重:4
图的邻接表为:
A->B:7
A->D:18
B->C:2
C->F:9
D->E:20
F->D:3
G->A:14
G->C:6
G->F:4
广度优先搜索遍历图:
G A C F B D E
深度优先搜索遍历图:
G A B C F D E
======================================
以邻接矩阵构图:
请按顺序输入顶点信息:A B C D E F G
请输入起点和终点:A B
请输入该边的权重:7
请输入起点和终点:A D
请输入该边的权重:18
请输入起点和终点:B C
请输入该边的权重:2
请输入起点和终点:C F
请输入该边的权重:9
请输入起点和终点:D E
请输入该边的权重:20
请输入起点和终点:F D
请输入该边的权重:3
请输入起点和终点:G A
请输入该边的权重:14
请输入起点和终点:G C
请输入该边的权重:6
请输入起点和终点:G F
请输入该边的权重:4
图的邻接矩阵为:
0 7 0 18 0 0 0
0 0 2 0 0 0 0
0 0 0 0 0 9 0
0 0 0 0 20 0 0
0 0 0 0 0 0 0
0 0 0 3 0 0 0
14 0 6 0 0 4 0
各个邻接边的信息:
A->B:7
A->D:18
B->C:2
C->F:9
D->E:20
F->D:3
G->A:14
G->C:6
G->F:4
广度优先搜索遍历图:
G A C F B D E
深度优先搜索遍历图
G A B C F D E
===========================================
D:\users\lenovo\source\数据结构作业源代码\数据结构-图\Debug\数据结构-图.exe (进程 224)已退出,返回代码为: 0。
按任意键关闭此窗口...