拓扑排序

Posted zcxhaha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序相关的知识,希望对你有一定的参考价值。

拓扑排序


1.存储结构

? 采用邻接表,在表节点中增加degree域,记录每个节点的入度。

2.实现步骤

? 1.先求每个节点的入度

? 2.借助栈,扫描一遍表,将入度为0的节点入栈

? 3.依次将栈中的节点出栈,每次出栈都将该节点的邻接点的入度减一(删去该点及以该点为尾的弧)

? 4.设置一个计数器,记录出栈节点的个数,如果全部出栈后,计数器的值等于图的顶点的个数,表明该图无环。

3.实现代码:

#include<stdio.h>
#include<stdlib.h>

#define MAX_VERTEX_NUM 20
#define STACK_INIT_SIZE 100              //最大容量
#define STACKINCREMENT 10                 //动态增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR -1
#define OVERFLOW -1

typedef char VertexType;
typedef int Status;              //函数的状态

/*-----------图的存储结构-----------*/
//弧结点
typedef struct ArcNode{
    int adjvex;      //该弧所指向的顶点的位置
    int value;
    struct ArcNode *nextarc;    //指向下一条弧
}ArcNode;

//表节点
typedef struct VNode{
    int degree;                 //顶点的入度
    VertexType data;            //顶点信息
    ArcNode * firstchild;       //指向第一条以自己为弧尾弧
}VNode, AdjList[MAX_VERTEX_NUM];

//邻接表
typedef struct{
    AdjList vertices;
    int vexnum, arcnum;
}ALGraph;
/*----------------------------------*/

typedef VNode ElemType;            //数据元素的类型 注意使用宏定义的好处
/*-----------栈的存储结构-----------*/
typedef struct
{
    ElemType * base;                //栈底
    ElemType * top;                 //栈顶
    int stacksize;                  //栈的当前已分配的空间
}SqStack;
/*---------------------------------*/

/*--------------------------栈的基本操作--------------------------*/
/*初始化空栈*/
Status InitStack(SqStack * S)
{
    S->base = S->top = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if (!S->base)
    {
        return FALSE;
    }

    S->stacksize = STACK_INIT_SIZE;
    return TRUE;
}

/*入栈*/
Status Push(SqStack * S, ElemType e)
{
    /*判断是否栈满*/
    if(S->top - S->base >= S->stacksize)
    {
        S->base = (ElemType *)realloc(S->base, (STACKINCREMENT+S->stacksize) * sizeof(ElemType));
        if (S->base == NULL)
        {
            printf("内存分配失败!
");
            return ERROR;
        }

        S->top = S->base + S->stacksize;
        S->stacksize = STACKINCREMENT+S->stacksize;
    }

    *(S->top) = e;
    S->top++;
}

/*出栈*/
Status Pop (SqStack * S, ElemType * e)
{
    if(S->base == S->top)
    {
        return ERROR;
    }

    (*e) = *(--(S->top));
    return OK;
}

/*判断是否为空栈*/
Status StackEmpty(SqStack * S)
{
    if (S->base == S->top)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
/*--------------------------------------------------------------------*/
//创建有向网
Status Creat_AlGraph(ALGraph &G)
{
    int vexnum, arcnum;
    int i;
    int c;
    int head, tail, value;        //弧头,弧尾,权值
    ArcNode * p;

    for(i = 0; i < MAX_VERTEX_NUM; ++i)
    {
        G.vertices[i].firstchild = NULL;
    }

    printf("请输入顶点的个数和弧的个数:
");
    scanf("%d%d", &vexnum, &arcnum);
    G.arcnum = arcnum;
    G.vexnum = vexnum;

    printf("请依次输入个顶点:
");
    for(i = 0; i < vexnum; ++i)
    {
        getchar();
        scanf("%c", &c);
        G.vertices[i].data = c;
    }

    printf("请依次输入各条弧(位置为在邻接表中的位置)的信息:
");
    for(i = 0; i < arcnum; ++i)
    {
//        scanf("%d%d%d", &head, &tail, &value);
        scanf("%d%d", &head, &tail);
        p = (ArcNode *)malloc(sizeof(ArcNode));
        if(!p)
        {
            exit(OVERFLOW);
        }
        p->value = value;
        p->adjvex = tail;

        //头插
        p->nextarc = G.vertices[head].firstchild;
        G.vertices[head].firstchild = p;
    }

    return OK;
}

//初始化各节点的入度
Status InitInDegree(ALGraph &G)
{
    ArcNode *p = NULL;
    int i;

    //先清零
    for(i = 0; i < G.vexnum; ++i)
    {
        G.vertices[i].degree = 0;
    }

    //求入度
    for(i = 0; i < G.vexnum; ++i)
    {
        p = G.vertices[i].firstchild;

        while(p)
        {
            G.vertices[p->adjvex].degree++;
            p = p->nextarc;
        }
    }

    return OK;
}

//拓扑排序
Status TopologicalSort(ALGraph &G)
{
    SqStack S;
    VNode e;
    ArcNode *p = NULL;
    int i;      //循环变量
    int count = 0;    //计数器

    InitStack(&S);
    InitInDegree(G);

    //将度为0的节点入栈
    for(i = 0; i < G.vexnum; ++i)
    {
        if(G.vertices[i].degree == 0)
        {
            Push(&S, G.vertices[i]);
        }
    }

    while(!StackEmpty(&S))
    {
        Pop(&S, &e);
        count++;
        printf("%c ", e.data);
        p = e.firstchild;

        while(p)
        {
            if(!(--G.vertices[p->adjvex].degree))
            {
                Push(&S, G.vertices[p->adjvex]);
            }

            p = p->nextarc;
        }
    }

    if(count < G.vexnum)
    {
        return ERROR;
    }
    else
    {
        return OK;
    }
}

int main(void)
{
    ALGraph G;
    Creat_AlGraph(G);
    TopologicalSort(G);
    return 0;
}

//测试数据
/*
A B C D E F G H I J K L
0 3
0 1
0 2
0 11
1 2
2 4
2 6
2 7
3 4
4 6
5 7
8 9
8 10
8 11
9 11
10 5
*/

以上是关于拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

拓扑排序代码:

使用 C# 代码实现拓扑排序

UVA10305 拓扑排序

【数据结构】请写出以下AOV网的拓扑排序序列

数据结构问题~啥图可以进行拓扑排序~啥图不能进行拓扑排序?

拓扑排序之变量序列代码