有向图的拓扑排序问题 -----邻接表存储:
这里的邻接表存储方式其中在vnnode结构体中加入了count(入度)。
在拓扑排序过程中,每次找读入为0的进栈,之后每出栈一个顶点就要循环遍历邻近所有(注意,这里的 所有)有边的顶点,修改对应的读入以及判断是否可以入栈.
下面代码以图顶点为例: 方便验证结果。
代码如下:
#include <stdio.h>
#include <malloc.h>
#define inf 330
#define max 50
typedef struct node{
int adjvex;
int weight; //权值
struct node *nextarc;
}arcnode;//定义结点的结构体类型
typedef struct {
arcnode *firstarc;
int count;
}vnnode; //定义头结点的结构体
typedef struct {
vnnode adjlist[max];
int n;
int e;
}adjgraph; //定义图表的结构体类型
//创建邻接图
void createadj(adjgraph *&g, int a[max][max], int n, int e)
{
arcnode *p;
//分配一段空间,并做相应的赋值操作。
g = (adjgraph *)malloc(sizeof(adjgraph));
g->n = n;
g->e = e;
//对头结点初始化为NULL
for(int i = 0 ;i <n; i++)
{
g->adjlist[i].firstarc = NULL;
g->adjlist[i].count = 0;
}
//循环找结点
for(int i =0; i<n; i++)
for(int j = n-1; j>=0; j--)
if(a[i][j]!=0 && a[i][j]!=inf)//如果有边
{
p = (arcnode *)malloc(sizeof(arcnode));
p->adjvex =j;
p->weight = a[i][j];
g->adjlist[j].count++;
//这里采用头插发
p->nextarc = g->adjlist[i].firstarc;
g->adjlist[i].firstarc = p;
}
}
//输入图的邻接表
void showadj(adjgraph *g)
{
arcnode *p;
for(int i =0; i< g->n; i++)
{
//首先指向头结点。
p = g->adjlist[i].firstarc;
printf("%d 入度:(%d): ",i+1,g->adjlist[i].count);
//这里是循环输出每个头结点的链表
while(p!=NULL)
{
printf("%d -->",p->adjvex+1);
p = p->nextarc;
}
printf("/\\");
printf("\n");
}
}
//拓扑排序输出
/*算法的主要思想,一个是找入度为0的顶点进栈,二个每次出栈一个顶点,
就要遍历其他相关有边的顶点,修改顶点入度,并判断是否入栈,不满足就寻找下一个相关有边的顶点。
*/
void tp(adjgraph *g)
{
arcnode *p;
//定义一个数组栈以及数组下标
int st[max];
int top = -1;
int j,k;//定义两个变量,下面需要用到
//这个循环用来遍历所有点,找到入度为0的点将其进栈。
for(int i=0; i<g->n; i++)
if(g->adjlist[i].count ==0)
{
top++;
st[top] = i;
}
//在栈不空的情况下,出栈一个顶点,然后将这个顶点的所有有边的另外一端的顶点循环判断,如果入度为0,则进栈。遍历完之后接着出栈一个顶点,在遍历....循环同样的操作
while(top>-1)
{
//出栈一个顶点
k = st[top];
printf("%d ",k+1);
top--;
//在遍历该出栈顶点的其他有边的顶点
p = g->adjlist[k].firstarc;
while(p!=NULL)
{
//度数-1
j = p->adjvex;
g->adjlist[j].count--;
//在判断是否可以入栈
if(g->adjlist[j].count == 0 )
{
top++;
st[top] =j;
}
//遍历下一个顶点。
p =p ->nextarc;
}
}
}
int main()
{
adjgraph *b;
int a[max][max] = {{0,inf,1,inf,inf,inf,inf},
{inf,0,inf,1,1,inf,1},
{inf,inf,0,1,inf,inf,inf},
{inf,inf,inf,0,1,1,inf},
{inf,inf,inf,inf,0,inf,inf},
{inf,inf,inf,inf,inf,0,inf},
{inf,inf,inf,inf,inf,1,0}};
int n= 7;
int e= 8;
createadj(b,a,n,e);
showadj(b);
printf("\n拓扑排序输出序列为: ");
tp(b);
return 0;
}
程序运行如下: