用邻接链表存储图并且实现拓扑排序

来源:互联网 发布:淘宝抢购手机 编辑:程序博客网 时间:2024/04/28 13:37
#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,否则返回0int StackEmpty(SqStack S){if (S.top == S.base)return 1;elsereturn 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,否则返回0int 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;}


原创粉丝点击