C++数据结构-拓扑排序

#include <iostream>
#include <cstdlib>
#define MAXVEX 6      //起始顶点数默认为6,可在此直接修改
#define MAXEDGE 8     //起始边的数默认为8,可在此直接修改
using namespace std;

//该代码是邻接表拓扑排序原理
//步骤1:在有向图中选一个没有前驱(即入度为0)的顶点(用栈来保存)且输出其信息
//步骤2:从图中删除该顶点(出栈)和所有以他为尾的弧(相邻顶点的入度-1)
//步骤3:重复上述两步,直至全部顶点均已输出或当前图中已不存在无前驱的顶点为止

//注意点1:下标0的位置都不用,所以要多开辟一个空间
//注意点2:头结点信息既可以是字符A,B,C,D,也可以是字符'1','2'...
//注意点3:在创建邻接表时,使用头插法将边结点接在头结点之后

typedef struct sqstack
{
    int *elem;
    int top;
}SqStack;                 //栈

typedef struct EdgeNode
{
    int adjvex;
    struct EdgeNode *next;
}EdgeNode;               //边结点

typedef struct
{
    char vextexinfo;     //存放头结点信息(如A,B,C,D)
    int in;              //存放头结点的入度信息
    EdgeNode *firstedge; //指向该结点的临边
}VextexNode,AdjList;     //头结点(即邻接表)

typedef struct
{
    int vexNum;                //顶点数
    int edgeNum;               //边数
    AdjList adjlist[MAXVEX+1]; //头结点数组
}ALGraph;


/*****************初始化静态栈******************/
void InitStack(SqStack & s)
{
    s.elem =new int[MAXVEX+1];
    if(s.elem == NULL)
    {
        cout<<"内存分配失败!!!退出程序"<<endl;
        exit(0); //需引入头文件<cstdlib>
    }
    s.top=0;
}

/******************压栈*************************/
//进栈是从下标1开始存放,0位置不存放数据
void Push(SqStack &s , int e)
{
    if(s.top >= MAXVEX)
    {
        cout<<"栈已满!!!"<<endl;
    }else
    {
        s.top++;
        s.elem[s.top]=e;
    }
}

/******************出栈*************************/
void Pop(SqStack &s , int &e)
{
    e=s.elem[s.top];
    s.top--;
}
/******************判断是否空栈*****************/
int Emptystack(SqStack &s)
{
    if(s.top<1)
        return 0;
    else
        return 1;
}

/******************初始化邻接表*******************/
void InitAdjList(ALGraph &g)
{
    g.vexNum=MAXVEX;
    g.edgeNum=MAXEDGE;
    //初始化头结点数组(即表头信息)
    for(int i =1; i<=MAXVEX ; i++)
    {
        cout<<"请输入第"<<i<<"个结点的信息:";
        cin>>g.adjlist[i].vextexinfo;
        g.adjlist[i].firstedge=NULL; //初始化指针指向空
    }
}

//通过两个结点来确认边,并得到这两个结点的在数组的下标位置
/*********************确定邻接表数组下标的位置*********************/
void Locata(ALGraph &g,char &vex1,char &vex2, int &m, int &n)
{
    for(int i =1;i<=MAXVEX;i++)
    {
        if(vex1 == g.adjlist[i].vextexinfo)
            m=i;
        if(vex2 == g.adjlist[i].vextexinfo)
            n=i;
    }
}
/******************建立邻接表*******************/
void SetAdjList(ALGraph &g)
{
    char vex1,vex2;
    int m,n;
    for(int i=1;i<=MAXEDGE;i++) //有几条边就循环几次
    {
         cout<<"请输入第"<<i<<"条边(形如A B,表示A到B的一条边)";
         cin>>vex1>>vex2; //输入边的信息(即通过输入两顶点来确认边)
         Locata(g,vex1,vex2,m,n);//得到vex1和vex2在邻接表的数组下标位置m和n
         EdgeNode *s1 = new EdgeNode;
         s1->adjvex=n;   //无向图现在m是头,n是尾
         s1->next = g.adjlist[m].firstedge;
         g.adjlist[m].firstedge=s1;
    }
    //初始化顶点的入度
    for(int i=1;i<=MAXVEX;i++)
    {
        cout<<"请输入第"<<i<<"个顶点的入度:";
        cin>>g.adjlist[i].in;
    }
}
/******************显示邻接表*******************/
void ShowAdjList(ALGraph &g)
{
    cout<<"该图的邻接表如下:"<<endl;
    for(int i=1;i<=g.vexNum ;i++)
    {
        EdgeNode *p;
        cout<<"结点"<<i<<" 其入度为:"<<g.adjlist[i].in<<"  其邻接点为: ";
        for(p = g.adjlist[i].firstedge; p!=NULL ; p=p->next)
            cout<<p->adjvex<<"  ";
        cout<<endl;
    }
}
/*********************拓扑排序**************************/
void Topological(ALGraph &g)
{
    //创建初始化一个栈
    SqStack s;
    InitStack(s);
    //第一轮找出结点入度为0的点压栈
    for(int i=1;i<=MAXVEX;i++)
    {
        if(g.adjlist[i].in == 0)
            Push(s,i);
    }
    cout<<"拓扑排序如下:"<<endl;
    while(Emptystack(s) != 0) //表示栈非空
    {
        int k;
        int e; //接收出栈的结点的下标
        Pop(s,e);//弹出出栈结点的下标
        cout<<g.adjlist[e].vextexinfo<<"->";
        EdgeNode *p = g.adjlist[e].firstedge;
        while(p != NULL)
        {
            k=p->adjvex;
            g.adjlist[k].in--;       //弹出e之后,还要把e相关的边去除,就是与e相邻的结点的入度减1
            if(g.adjlist[k].in == 0) //结点入度减1完之后,如果是0,就再次进栈
                Push(s,k);           //将入度为0的结点下标压栈
            p=p->next;               //指向e的下一个结点
        }
    }
}

int main()
{
    ALGraph g;
    InitAdjList(g);
    SetAdjList(g);
    ShowAdjList(g);
    Topological(g);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43323201/article/details/84786514