图的基本算法实现
实验目的:
用邻接表存储方式存储有向图,并实现以下相关算法:
1、创建有向图的邻接表
2、分别用深度优先和广度优先遍历有向图
3、对创建的有向图进行拓扑排序
实验代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define SIZE 20 //动态分配栈内存,栈的最大容量(stacksize)
#define MORE 10 //入栈空间变大
#define MVNum 100 //最大顶点数
#define max 20
typedef int Status;
typedef char VertexType;
typedef struct ArcNode { //边节点
int adjvex; //该边所指向顶点的位置
struct ArcNode * nextarc;//指向下一条边的指针
//OtherInfo info; //和边相关的信息(权值)
} ArcNode;
typedef struct VNode { //顶点信息
VertexType data;
ArcNode * firstarc; //指向第一条依附该顶点的边的指针
} VNode,AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct {
AdjList vertices;
int vexnum,arcnum; //图当前的顶点数和边数
} ALGraph;
typedef struct {
int *base;
int *top;
int stacksize;
} SqStack;
void InitStack(SqStack &S) {
S.base = (int *) malloc(SIZE*sizeof(int));
if(!S.base) return;
S.top = S.base;
S.stacksize = SIZE;
}
int StackEmpty(SqStack &S) {
if(S.base == S.top) return 1;
else return 0;
}
void Push(SqStack &S, int e) {
if(S.top - S.base >= S.stacksize) { //栈满则扩大内存
S.base = (int *)realloc(S.base,(S.stacksize + MORE)*sizeof(int));
if(!S.base) exit(0);
S.top = S.base + S.stacksize;
S.stacksize += MORE;
}
*S.top++=e;
}
void Pop(SqStack &S,int &e) {
if(S.top == S.base) exit(0);
else e = *--S.top;
}
void GetTop(SqStack &S, int &e) {
if(S.top == S.base) exit(0);
else e = *(S.top - 1);
}
void CreatGraph(ALGraph &G) {
int i, s, e;
ArcNode *p,*q;
printf("请输入顶点个数和边的个数(中间以空格隔开):");
scanf("%d%d",&G.vexnum,&G.arcnum);
getchar();
printf("请输入顶点序号: ");
for(i = 1; i<= G.vexnum; i++) {
scanf("%c",&G.vertices[i].data);
G.vertices[i].firstarc = NULL;
}
getchar();
printf("请依次输入每一条边依附的起点序号和终点序号(中间以空格隔开):\n");
for(i = 1; i <= G.arcnum; i++) {
scanf("%d%d",&s,&e);
getchar();
p = (ArcNode *) malloc (sizeof(ArcNode));
p->nextarc = NULL;
p->adjvex = e;
q = G.vertices[s].firstarc;
if(!q)
G.vertices[s].firstarc = p;
else {
while(q->nextarc) {
q = q->nextarc;
}
q->nextarc = p;
}
}
}
void PrintGraph(ALGraph G) {
int i;
printf("打印有向图:\n");
for(i = 1; i <= G.vexnum; i++) {
printf("%3c",G.vertices[i].data);
if(G.vertices[i].firstarc == NULL) {
printf("\n");
continue;
}
while(G.vertices[i].firstarc) {
printf("%3d",G.vertices[i].firstarc->adjvex);
G.vertices[i].firstarc = G.vertices[i].firstarc->nextarc;
}
printf("\n");
}
}
void DfsTraverse(ALGraph G, int v) {
//从第v个顶点出发深度优先搜索遍历图G
int visited1[max];
int n, i;
for(i = 1; i <= G.vexnum; i++) {
visited1[i] = 0;
}
ArcNode *p;
SqStack S;
InitStack(S);
visited1[v] = 1;
printf("%c",G.vertices[v].data);
Push(S,v);
while(!StackEmpty(S)) {
GetTop(S,v);
p = G.vertices[v].firstarc;
while(p)
if(visited1[p->adjvex])
p =p->nextarc;
else {
printf("%c",G.vertices[p->adjvex].data);
visited1[p->adjvex] = 1;
Push(S,p->adjvex);
p = G.vertices[p->adjvex].firstarc;
}
if(!StackEmpty(S)) {
Pop(S,n);
}
}
}
int q[max],f=0,r = 0;
int visited2[max];
void BfsTraverse(ALGraph G, int s) {
//广度优先搜索遍历(递归)
ArcNode *p;
if(!visited2[s]) {
printf("%c",G.vertices[s].data);
visited2[s] = 1;
p = G.vertices[s].firstarc;
while(p) {
if(!visited2[p->adjvex])
q[r++] = p->adjvex;
p = p->nextarc;
}
}
while(f < r) {
BfsTraverse(G,q[f++]);
}
}
void FindInDegree(ALGraph G, int indegree[]) {
//求顶点入度
ArcNode *p;
int i;
for(i = 1; i<= G.vexnum;i++) //初始化
indegree[i] = 0;
for(i = 1;i <= G.vexnum;i++) {
p =G.vertices[i].firstarc;
while(p) {
indegree[p->adjvex]++;
p = p->nextarc;
}
}
}
void TopologicalSort(ALGraph G) {
//拓扑排序
ArcNode *p;
SqStack S;
int count;
int i,k,indegree[max];
FindInDegree(G,indegree);
InitStack(S);
for(i = 1;i <= G.vexnum;i++)
if(!indegree[i]) Push(S,i);
count = 0;
while(!StackEmpty(S)) {
Pop(S,i);
printf("%c",G.vertices[i].data);
count++;
for(p = G.vertices[i].firstarc;p;p = p->nextarc) {
k = p->adjvex;
if(!(--indegree[k])) Push(S,k);
}
}
if(count < G.vexnum) {
printf("该图有回路,无法拓扑排序\n");
exit(0);
}
}
int main() {
ALGraph G;
printf("\n******创建一个图********\n");
CreatGraph(G);
printf("\n******深度优先搜索遍历********\n");
DfsTraverse(G,1);
printf("\n******广度优先搜索遍历********\n");
BfsTraverse(G,1);
printf("\n******拓扑排序********\n");
TopologicalSort(G);
return 0;
}
运行结果如下:
这个输入方式需要自己去理解图,这个图需要你去脑补了,如果能把这个图画出来,我感觉对图也就基本掌握了。