11、 拓扑排序

自闭症网瘾萝莉.ら 提交于 2020-03-09 00:38:42

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。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!