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。
来源:CSDN
作者:hopegrace
链接:https://blog.csdn.net/hopegrace/article/details/104728035