#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#define MAX_NUM 100 // 图的点的个数
#define ERROR -1
typedef struct ArcNode{
int adjvex; // 顶点所在的位置
struct ArcNode *nextarc; // 下一条边的指针
}ArcNode;
typedef struct VNode{
char data; // 顶点信息
ArcNode * firsearc; // 指向第一条依附该顶点的边的指针
}VNode , AdjList[MAX_NUM];
typedef struct{
AdjList vertices;
int vexnum,arcnum; // 图当前的顶点数和边数
}ALGraph;
/*********************创建邻接表**********************************************/
void CreatALGraph(ALGraph &G){ // 创建无向图的邻接表
int i,j,k;
ArcNode *s,*p;
printf("请输入该无向图的顶点数及边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
printf("请输入顶点信息(为字符型):\n");
for( i = 0 ; i < G.vexnum ; ++i ){
printf("请输入第%d个顶点的信息:",i+1);
scanf("%*c%c",&G.vertices[i].data);
G.vertices[i].firsearc = NULL;
}
printf("请输入边的信息(格式为:i,j):\n");
for( k = 0 ; k < G.arcnum ; ++k ){
printf("请输入第%d条边的信息:",k+1);
scanf("%d %d",&i,&j);
p = (ArcNode *)malloc(sizeof(ArcNode));
if(!p) exit(ERROR);
s = (ArcNode *)malloc(sizeof(ArcNode));
if(!s) exit(ERROR);
s->adjvex = j;
if(G.vertices[i].firsearc == NULL || G.vertices[i].firsearc->adjvex < j){
s->nextarc = G.vertices[i].firsearc;
G.vertices[i].firsearc = s;
}
else{
for( p = G.vertices[i].firsearc;(p->nextarc) && p->nextarc->adjvex > j;p = p->nextarc )
;
s->nextarc = p->nextarc;
p->nextarc = s;
}
s = (ArcNode *)malloc(sizeof(ArcNode));
if(!s) exit(ERROR);
s->adjvex = i;
if(G.vertices[j].firsearc == NULL || G.vertices[j].firsearc->adjvex < i){
s->nextarc = G.vertices[j].firsearc;
G.vertices[j].firsearc = s;
}
else{
for( p = G.vertices[j].firsearc;(p->nextarc) && p->nextarc->adjvex > i;p = p->nextarc )
;
s->nextarc = p->nextarc;
p->nextarc = s;
}
}
}
void creatALGraph(ALGraph &G){ // 创建有向图的邻接表
int i,j,k;
ArcNode *s,*p;
printf("请输入该有向图的顶点数及边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
printf("请输入顶点信息(为字符型):\n");
for( i = 0 ; i < G.vexnum ; ++i ){
printf("请输入第%d个顶点的信息:",i+1);
scanf("%*c%c",&G.vertices[i].data);
G.vertices[i].firsearc = NULL;
}
printf("请输入边的指向信息(格式为:i j):\n");
for( k = 0 ; k < G.arcnum ; ++k ){
printf("请输入第%d条边的信息:",k+1);
scanf("%d %d",&i,&j);
p = (ArcNode *)malloc(sizeof(ArcNode));
if(!p) exit(ERROR);
s = (ArcNode *)malloc(sizeof(ArcNode));
if(!s) exit(ERROR);
s->adjvex = j;
if(G.vertices[i].firsearc == NULL || G.vertices[i].firsearc->adjvex < j){
s->nextarc = G.vertices[i].firsearc;
G.vertices[i].firsearc = s;
}
else{
for( p = G.vertices[i].firsearc;(p->nextarc) && p->nextarc->adjvex > j;p = p->nextarc )
;
s->nextarc = p->nextarc;
p->nextarc = s;
}
}
}
void PrintfALGraph( ALGraph G ){ // 输出邻接表
int v;
ArcNode *p = (ArcNode *)malloc(sizeof(ArcNode));
for( v = 0 ; v < G.vexnum ; ++v ){
printf("%d %c",v,G.vertices[v].data); // 输出顶点信息
for( p = G.vertices[v].firsearc ; p != NULL ; p = p->nextarc )
printf("->%d",p->adjvex); // 输出与该顶点相关联的点的序号
printf("\n");
}
}
/*********************深度优先搜索********************************************/
bool visited[MAX_NUM],flag; // visited 记录顶点是否被访问过,flag 控制输出
void DFS( ALGraph G , int v , bool flag ){ // 搜索与顶点相关联的点
visited[v] = true;
if( flag ){ // flag为true时
printf("->%c",G.vertices[v].data);
}
else{
flag = true; // flag默认初始为false,输出访问到的第一个顶点后 变为true
printf(" %c",G.vertices[v].data);
}
ArcNode *s = (ArcNode *)malloc(sizeof(ArcNode));
if(!s) exit(ERROR);
if( G.vertices[v].firsearc != NULL )
for( s = G.vertices[v].firsearc ; s != NULL ; s = s->nextarc )
if(!visited[s->adjvex]) // 若未被访问,则DFS递归,访问该顶点
DFS(G,s->adjvex,flag);
}
void DFSTraverse( ALGraph G ){ // 搜索图的每一个顶点
int v,ch;
for( v = 0 ; v < G.vexnum ; ++v)
visited[v] = false; // 初始化visited为false
printf("请输入需要搜索的点的序号:");
scanf("%d",&ch);
flag = false;
DFS(G,ch,flag);
printf("\n");
for( v = 0 ; v < G.vexnum ; ++v)
if( !visited[v] ){
flag = false; // flag初始为false
DFS(G,v,flag);
printf("\n");
}
}
/*********************广度优先搜索********************************************/
bool visit[MAX_NUM]; // visit 记录顶点是否被访问过
typedef struct QNode{ // 链式队列结点
int base;
struct QNode *next;
}QNode;
typedef struct Queue{ // 链式队列
QNode *front;
QNode *rear;
}Queue;
Queue *CreatQueue(){ // 创建队列
Queue *Q = (Queue *)malloc(sizeof(Queue));
if(!Q) exit(ERROR);
Q->front = Q->rear = NULL;
return Q;
}
int QueueEmpty( Queue Q ){ // 判断队列是否为空
if( Q.front == NULL )
return 1;
else return 0;
}
void EnQueue( Queue &Q , int &v ){ // 入队
QNode *p = (QNode *)malloc(sizeof(QNode));
if(!p) exit(ERROR);
p->base = v;
p->next = NULL;
if( QueueEmpty(Q) )
Q.front = Q.rear = p;
else{
Q.rear->next = p ;
Q.rear = p;
}
}
void DeQueue( Queue &Q , int &u ){ // 出队
u = Q.front->base;
Q.front = Q.front->next;
}
void BFS( ALGraph G , int v , Queue &Q ){ // 搜索与该顶点相关联的点
int u;
ArcNode *s;
visit[v] = true;
printf(" %c",G.vertices[v].data);
EnQueue(Q,v); // 该次访问的第一个顶点入队
while( !QueueEmpty(Q) ){ // 队空跳出
DeQueue(Q,u);
for( s = G.vertices[u].firsearc ; s != NULL ; s = s->nextarc ) // 依次访问与v顶点相关联的点
if( !visit[s->adjvex] ){ // 若未被访问,则入队并记录
visit[s->adjvex] = true;
EnQueue(Q,s->adjvex);
printf("->%c",G.vertices[s->adjvex].data);
}
}
}
void BFSTraverse( ALGraph G ){ // 搜索每一个顶点
int v,ch;
Queue Q = *CreatQueue();
for( v = 0 ; v < G.vexnum ; ++v )
visit[v] = false; // 初始化visit数组为false
printf("请输入需要搜索的点的序号:");
scanf("%d",&ch);
BFS(G,ch,Q);
printf("\n");
for( v = 0 ; v < G.vexnum ; ++v )
if( !visit[v] ){ // 对未访问到的顶点 继续访问
BFS(G,v,Q);
printf("\n");
}
}
/*********************拓扑排序************************************************/
int InDegree[MAX_NUM],Num[MAX_NUM]; // InDegree 记录每一个顶点的入度 Num存储拓扑排序出栈的顶点
typedef struct SNode{ // 链栈结点
int bata;
struct SNode *next;
}SNode;
typedef struct Stack{ // 链栈
SNode *top;
}Stack;
Stack *CreatStack(){ // 创建链栈
Stack *S = (Stack *)malloc(sizeof(Stack));
if(!S) exit(ERROR);
S->top = NULL;
return S;
}
int StackEmpty( Stack S ){ // 判断链栈是否为空
if( S.top == NULL )
return 1;
else return 0;
}
int GetTop( Stack S ){ // 获取栈顶元素
if( !StackEmpty(S) )
return S.top->bata;
}
void Push( Stack &S , int e ){ // 压栈
SNode *p = (SNode *)malloc(sizeof(SNode));
if(!p) exit(ERROR);
p->bata = e;
p->next = S.top;
S.top = p;
}
void Pop( Stack &S , int &e ){ // 出栈
SNode *p;
p = S.top;
e = p->bata;
S.top = p->next;
free(p);
}
void TopologicalSort( ALGraph G ){ // 拓扑排序
int v,u;
ArcNode *s;
memset(InDegree,0,sizeof(InDegree));
for( v = 0 ; v < G.vexnum ; ++v ){ // 计算每个顶点的入度
for( s = G.vertices[v].firsearc ; s != NULL ; s = s->nextarc )
InDegree[s->adjvex]++;
}
Stack S = *CreatStack();
for( v = 0 ; v < G.vexnum ; ++v ) // 入度为0的顶点进栈
if( !InDegree[v] )
Push(S,v);
int count = 0; // 对输出顶点计数
while( !StackEmpty(S) ){
Pop(S,u);
Num[count++] = u; // 将u顶点存入Num 并计数
for( s = G.vertices[u].firsearc ; s != NULL ; s= s->nextarc ){
u = s->adjvex;
if( !(--InDegree[u]) ) // 对u号顶点的每一个邻接点的入度减 1
Push(S,u); // 若入度减为0,则入栈
}
}
if( count < G.vexnum ) // 该有向图有回路
printf("该有向图存在回路!\n拓扑到的结果为:\n");
else
printf("拓扑排序后的结果:\n");
for( v = 0 ; v < count ; ++v ) // 输出拓扑排序到的顶点
printf(" %c ",G.vertices[Num[v]].data);
printf("\n\n");
}
/*********************主操作**************************************************/
void Choose1(){ // 无向图操作
ALGraph G;
CreatALGraph(G);
printf("***********************************\n");
printf("此无向图的邻接表为:\n");
PrintfALGraph(G);
printf("\n深度优先搜索的结果:\n");
DFSTraverse(G);
printf("\n广度优先搜索的结果:\n");
BFSTraverse(G);
}
void Choose2(){ // 有向图操作
ALGraph G;
creatALGraph(G);
printf("***********************************\n");
printf("此有向图的邻接表为:\n");
PrintfALGraph(G);
printf("\n深度优先搜索的结果:\n");
DFSTraverse(G);
printf("\n广度优先搜索的结果:\n");
BFSTraverse(G);
TopologicalSort(G);
}
int GetChoose( int min , int max ){ // 获取操作选择
int choose;
while(1){
scanf("%d",&choose);
if( choose >= min && choose <= max )
return choose;
else printf("输入错误!请重新输入!\n");
}
}
int main(){
while(1){
printf("***********************************\n");
printf("请选择:\n");
printf("1、创建无向图并对其进行搜索\n");
printf("2、创建有向图并对其进行搜索及拓扑排序\n");
printf("3、结束\n");
int choose = GetChoose(1,3);
system("cls"); // 清屏
if( choose == 1 )
Choose1();
if( choose == 2 )
Choose2();
if( choose == 3 )
break;
}
return 0;
}
图的广搜、深搜及拓扑排序
最新推荐文章于 2022-09-23 19:10:34 发布