拓扑排序

简单的数据结构拓扑排序 高分 哦 有注释 能动 可加

  1、堆栈

  栈是一种特殊的线性表,插入或删除栈元素的运算只能在表的一端进行,称运算的一端为栈顶,另一端称为栈底。队列也是一种特殊的线性表(基本操作都是线性操作的子集)。

  特点:后进先出

  栈又称为“后进先出”的线性表,简称LIFO表。

  栈的链式实现是以链表作为栈的存储结构,并在这种存储结构上实现栈的基本运算。栈的链式实现称为链栈。

  2、有向无环图

  描述含有公共子式的表达式的有效工具;

  描述一项工程或系统的进行过程的有效工具。

  3、一些概念

  通常我们把计划、施工过程、生产流程、程序流程等都当成一个工程,一个大的工程常常被划分成许多较小的子工程,这些子工程称为活动。这些活动完成时,整个工程也就完成了。

  我们用一种有向图来表示这些工程、计划等,在这种有向图中,顶点表示活动,有向边表示活动的优先关系,这种用顶点表示活动,用弧来表示活动间的优先关系的有向图叫做顶点表示活动的网络(Actire On Vertices)简称为AOV网。

  拓扑排序:

  假设G=(V,E)是一个具有n个顶点的有向图,V中顶点序列vl,v2,…,vn称做一个拓扑序列(TopologicalOrder),当且仅当该顶点序列满足下列条件:若在有向图G中存在从顶点vi到vj的一条路径,则在顶点序列中顶点vi必须排在顶点vj之前。通常,在AOV网中,将所有活动排列成一个拓扑序列的过程叫做拓扑排序(Topological Sort)。

  在AOV网中不应该出现有向环。因为环的存在意味着某项活动将以自己为先决条件,显然无法形成拓扑序列。

  判定网中是否存在环的方法:对有向图构造其顶点的拓扑有序序列,若网中所有顶点都出现在它的拓扑有序序列中,则该AOV网中一定不存在环。

  4、拓扑排序的算法思想

  输入AOV网络。令 n 为顶点个数。

  (1)在AOV网络中选一个没有直接前驱的顶点,并输出之;

  (2)从图中删去该顶点, 同时删去所有它发出的有向边;

  重复以上步骤,直到全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;或图中还有未输出的顶点,但已跳出处理循环。这说明图中还剩下一些顶点,它们都有直接前驱,再也找不到没有前驱的顶点了。这时AOV网络中必定存在有向环。

  5、拓扑排序算法的C语言描述

  在实现拓扑排序的算法中,采用邻接表作为有向图的存储结构,每个顶点设置一个单链表,每个单链表有一个表头结点,在表头结点中增加一个存放顶点入度的域count,这些表头结点构成一个数组。

  为了避免重复检测入度为0的点,另设一栈存放所有入度为0的点。

  对于有n个顶点和e条边的有向图而言,for循环中建立入度为0的顶点栈时间为O(n);若在拓扑排序过程中不出现有向环,则每个顶点出栈、入栈和入度减1的操作在while循环语句中均执行e次,因此拓扑排序总的时间花费为O (n+e)。

  6、拓扑排序算法的C语言实现

  #include"stdio.h"

  #define MAX_VERTEX_NUM20

  #include"conio.h"

  #include"stdlib.h"

  #define STACK_INIT_SIZE16

  #define STACKINCREMENT5

  typedef  int SElemType;

  typedef charVertexType;

  

  typedef struct

  {

  SElemType *base;

  SElemType *top;

  int stacksize;

  }SqStack;

  

  

  //我们依然用邻接表来作图的存储结构

  typedef struct ArcNode{

  int adjvex;

  struct ArcNode *nextarc;

  int info;

  }ArcNode;  //表结点类型

  

  typedef struct VNode{

  VertexType data;

  int count;

  ArcNode *firstarc;

  }VNode,AdjList[MAX_VERTEX_NUM];//头结点

  

  typedef struct{

  AdjList vertices;  //邻接表

  int vexnum,arcnum;

  }ALGraph;

  

  int InitStack(SqStack&S)

  {

  S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));

  if(!S.base) exit(-1);

  S.top=S.base;

  S.stacksize=STACK_INIT_SIZE;

  return 1;

  }//InitStack

  

  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(-1);

  S.top=S.base+S.stacksize;

  S.stacksize+=STACKINCREMENT;

  }//if

  *(S.top)=e;

  S.top++;

  return 1;

  }//Push

  

  int Pop(SqStack&S,SElemType &e)

  {

  if(S.top==S.base)return 0;

  --S.top;

  e=*S.top;

  return 1;

  }//Pop

  

  int StackEmpty(SqStack&S)

  {

  if(S.top==S.base)return 1;

  else return 0;

  }//StackEmpty

  

  int LocateVex(ALGraphG,char u)

  {

  int i;

  for (i=0;i<G.vexnum;i++)

  { if(u==G.vertices[i].data) return i; }

  if (i==G.vexnum) {printf("Error u!\n");exit(1);}

  return 0;

  }

  

  voidCreateALGraph_adjlist(ALGraph &G)

  {

  int i,j,k,w;

  char v1,v2,enter;

  ArcNode *p;

  printf("Input vexnum &arcnum:\n");

  scanf("%d",&G.vexnum);

  scanf("%d",&G.arcnum);

  printf("Input Vertices(以回车隔开各个数据):\n");

  for (i=0;i<G.vexnum;i++)

  {     scanf("%c%c",&enter,&G.vertices[i].data);//注意点,解说

  G.vertices[i].firstarc=NULL;

  }//for

  

  printf("InputArcs(v1,v2,w)以回车分开各个数据:\n");

  for (k=0;k<G.arcnum;k++)

  {

  scanf("%c%c",&enter,&v1);

  scanf("%c%c",&enter,&v2);

  //scanf("%d",&w);

  i=LocateVex(G,v1);

  j=LocateVex(G,v2);

  p=(ArcNode*)malloc(sizeof(ArcNode));

  p->adjvex=j;

  //p->info = w;

  p->nextarc=G.vertices[i].firstarc; //前插法,即每次都插入到头结点的后面

  G.vertices[i].firstarc=p;

  printf("Next\n");

  }//for

  return;

  }//CreateALGraph_adjlist

  

  voidFindInDegree(ALGraph &G)

  {

  int i,j;

  for(i=0;i<G.vexnum;i++)

  {

  G.vertices[i].count=0;

  }//for

  for(j=0;j<G.vexnum;j++)

  {

  //G.vertices[i].count++;

  for(ArcNode*p=G.vertices[j].firstarc;p;p=p->nextarc)

  G.vertices[p->adjvex].count++;

  }//for

  }//FindInDegree

  

  int TopoSort(ALGraph&G)

  {

  SqStack S;

  FindInDegree(G);

  InitStack(S);

  for(inti=0;i<G.vexnum;i++)

  if(G.vertices[i].count==0) Push(S,i);

  int countt=0;

  while(!StackEmpty(S))

  {

  int i,m;

  m=Pop(S,i);

  printf(" %c",G.vertices[i].data); ++countt;

  for(ArcNode *p=G.vertices[i].firstarc;p;p=p->nextarc)

  {   int k;

  k=p->adjvex;

  if(!(--G.vertices[k].count)) Push(S,k);

  }//for

  }//while

  if(countt<G.vexnum) return 0;

  else return 1;

  }//TopoSort

  

  int main()

  {

  ALGraph G;

  CreateALGraph_adjlist(G);

  TopoSort(G);

  return 1;

  }

  7、malloc函数和realloc函数

  realloc: void *realloc(void *block, size_t size),将block所指存储块调整为大小size,返回新块的地址。如能满足要求,新块的内容与原块一致;不能满足要求时返回NULL,此时原块不变。

malloc:void *malloc(size_t size):分配一块足以存放大小为size的存储,返回该存储块的地址,不能满足时返回NULL。

温馨提示:答案为网友推荐,仅供参考