#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 3
#define MaxVernum 20
int degree[MaxVernum];
typedef char VertexType;
//typedef int Weight;
//存储图的边
typedef struct ArcNode
{
int Ver;//存储边所指向的顶点
int Weight;//存储该边的权重
struct ArcNode *next;//指向下一个边的指针结点
}ArcNode;
//存储图的顶点
typedef struct VerNode
{
VertexType data;//存储该顶点的数据
struct ArcNode *firstArc;// 边的头指针
int indegree;//该结点的入度
int flag;//设定一个标志用于后期判断最短路径是一条还是多条
}VerNode, AdjList[MaxVernum];
//存储图
typedef struct
{
AdjList adjlist;
int Arcnum;//存储图中的边的数目
int Vernum;//存储图中的顶点的数目
}ALGraph;
int IfArc(ALGraph *G, char a)//检查用户再次输入顶点是否在图中
{
int i = 0;
for (i = 0; i < G->Vernum; i++)
{
if (a == G->adjlist[i].data)
return i;//如果输入的顶点和图中某一顶点数值相同返回该顶点在图中的位置,return i之后就不会再执行函数之后的内容
}
return -1;//如果for循环结束之后还没有找到对应的值那么函数返回值为-1
}
//构造函数 创建图
void CreateALGraph(ALGraph *G)
{
char v1, v2;
int i = 0;
int w = 0;
int m = 0;
int n = 0;
ArcNode *p;
printf("请输入你想组建图的顶点总数和弧边总数:\n");
scanf("%d %d", &G->Vernum, &G->Arcnum);
for (i = 0; i < G->Vernum; i++)//初始化图中的顶点信息
{
fflush(stdin);//清空缓存区以免将上一步的空格回车等信息输入
printf("请输入第%d个顶点", i + 1);
scanf("%c", &G->adjlist[i].data);//给所有顶点数据进行初始化
G->adjlist[i].firstArc = NULL;//将每个顶点的头指针,以及入度初始化
G->adjlist[i].flag = 0;
G->adjlist[i].indegree = 0;
}
system("cls");
for (i = 0; i < G->Arcnum; i++)//初始化图中的弧边信息
{
fflush(stdin);
printf("请输入两顶点以及之间的权重(v1,v2,w):\n");
scanf("%c %c %d", &v1, &v2, &w);
m = IfArc(G, v1);
n = IfArc(G, v2);
if (m == -1 || n == -1)//只要其中任何一个顶点不在图中要求重新输入
{
i = i - 1;//因为这次输入数据错误所以将i减去1,不增加循环次数
printf("输入顶点数据错误请重新输入\n");//输出错误信息
continue;//跳过本次循环不再对边的其他内容进行操作
}
p = (ArcNode*)malloc(sizeof(ArcNode));//对p进行空间分配分配的大小是一个ArcNode结构体的大小
p->Ver = n;//顶点信息
p->Weight = w;//权重信息
p->next = G->adjlist[m].firstArc;//将刚刚输入的两个顶点链接起来
G->adjlist[m].firstArc = p;
G->adjlist[n].indegree++;
}
system("cls");
}
//栈类型
typedef int SElemType;
#define STACK_INIT_SIZE 10 //存储空间初始分配量
#define STACKINCREMENT 2 //存储空间分配增量
//栈的顺序存储结构表示
typedef struct SqStack
{
SElemType *base; //基地址
SElemType *top; //栈顶指针
int stacksize; //当前已经分配的存储空间
}SqStack;
//构造一个空栈
int InitStack(SqStack &S)
{
//为栈底分分配一个指定大小的存储空间
(S).base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if (!(S).base)
exit(0);
(S).top = (S).base; //栈底与栈顶指针相同
(S).stacksize = STACK_INIT_SIZE;
return 1;
}
//若栈S为空栈(栈底指针和栈顶指针相同), 则返回1,否则返回0
int StackEmpty(SqStack S)
{
if (S.top == S.base)
return 1;
else
return 0;
}
//插入元素e为新的栈顶元素
int Push(SqStack *S, SElemType e)
{
if ((*S).top - (*S).base >= (*S).stacksize)
{
(*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize + STACKINCREMENT)*sizeof(SElemType));
if (!(*S).base)
exit(0);
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
*((*S).top)++ = e;
return 1;
}
//若栈不为空,则删除S栈顶元素用e返回其值,并返回1,否则返回0
int Pop(SqStack *S, SElemType &e)
{
if ((*S).top == (*S).base)
{
return 0;
}
e = *--(*S).top;
return 1;
}
void Finedegree(ALGraph *G)
{
int j = 0;
for (j = 0; j<G->Vernum; j++)
{
degree[j]=G->adjlist[j].indegree;
printf("第%d个顶点即%c入度为:%d\n", j + 1,G->adjlist[j].data, degree[j]);
}
}
//有向图的G采用邻接表存储结构,若G无回路,则输出G的顶点的一个拓扑结构
int TopologicalSort(ALGraph *G)
{
int i, k;
int count = 0;
SqStack S;
ArcNode *p;
int e = 0;
int j = 0;
p = NULL;
InitStack(S);
Finedegree(G);
for (i = 0; i<G->Vernum; i++)
{
if (!degree[i])
Push(&S, i);//把入度为零的节点压栈
}
printf("拓扑排列如下:\n");
while (!StackEmpty(S))
{
Pop(&S, i);
printf("%c", G->adjlist[i].data);
count++;
for (p = G->adjlist[i].firstArc; p;p=p->next)
{
k = p->Ver;
if (!(--degree[k]))
Push(&S, k);
}
}
if (count < G->Vernum)
printf("有环");
return 0;
}
int main()
{
ALGraph f;
printf("请选择有向图");
CreateALGraph(&f);
TopologicalSort(&f);
system("pause");
return 0;
}
用邻接链表存储图并且实现拓扑排序
原文作者:拓扑排序
原文地址: https://blog.csdn.net/Hanani_Jia/article/details/78868169
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/Hanani_Jia/article/details/78868169
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。