拓扑排序代码 & 双向链表(带头尾指针)代码记录

本文介绍了如何使用C++编程语言实现AOV网(有向无环图)的拓扑排序算法,通过邻接表表示图结构,利用双向链表队列实现广度优先遍历,给出一个输入例子并展示了输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AOV网

表示工程的有向图,一定是个DAG(有向无环)网

拓扑序列

根据AOV网作出的流程顺序

拓扑排序

思路:
标记点的入度,从入度为0的开始,访问一个点,删除它对应的边,更新其他点的入度,重复,直到所有的点全部输出(点没输出完,剩余顶点没有入度为0的顶点,说明可能有环

代码(使用C++

使用了自己写的双向链表式队列,实现待处理拓扑排序点的存放

#include<iostream>
#include <cstring>
using namespace std;

#pragma region //链队列实现广度优先拓扑排序,用栈则会得到深度优先(我取的叫法,不知道别人怎么叫的

struct MyQueNode
{
    int data;   //将用于存储入度为0的顶点下标
    MyQueNode* next;
    MyQueNode* prev;
    MyQueNode()
    {
        data = -1;
        next = prev = nullptr;
    }
    MyQueNode(int data_)
    {
        data = data_;
        next = prev = nullptr;
    }
};

struct MyQue
{
    MyQueNode* head;
    MyQueNode* tail;
    MyQue()
    {
        head = tail = nullptr;
    }
    void push_back(int data_);
    void pop();
    int front();
    bool empty();
};

void MyQue::push_back(int data_)
{
    MyQueNode* p = new MyQueNode(data_);
    if(tail == nullptr)//链表为空情况
    {
        head = tail = p;
        return;
    }
    p->prev = tail;
    tail->next = p;
    tail = p;
}

int MyQue::front()
{
    return head->data;
}

void MyQue::pop()
{
    MyQueNode* p = head;
    if(head==tail)//链表剩一个结点情况(默认不会错误使用pop
        tail = nullptr;
    head = p->next;
    delete p;
}

bool MyQue::empty()
{
    return head == nullptr;
}
#pragma endregion

#pragma region //全局变量
const int N = 105;
#pragma endregion

#pragma region //邻接表图的结构体
struct Edge
{
    int vexP;   //邻接的点的下标
    Edge* next; //下一条边
    Edge(){ next = nullptr;}
};

struct Vex
{
    char val;       //顶点字符值
    Edge* first;    //边链表
    Vex(){first = nullptr;}
};

struct Graph
{
    int n;
    Vex g[N];
    int* topo;
    void getTopo();
    void addEdge(int a, int b);
    Graph(){topo =nullptr;}
    int find(char c);
};

int Graph::find(char c)
{
    for (int i = 0; i < n; i++)
    {
        if(g[i].val == c)
            return i;
    }
    return -1;
}

void Graph::addEdge(int a, int b)
{
    Edge* e = new Edge;
    e->vexP = b;
    e->next = nullptr;
    if( g[a].first )
    {
        e->next = g[a].first;
    }
    g[a].first = e;
}

void Graph::getTopo()
{
    MyQue q;
    if(topo !=nullptr )
        delete[] topo;
    topo = new int[n];
    int* ind = new int[n];
    memset(ind,0,sizeof(int)* n);

    for (int i = 0; i < n; i++)//记录所有顶点入度
    {
        Edge* e = g[i].first;
        while(e)
        {
            ind[e->vexP]++;
            e = e->next;
        }
    }

    /*
    for (int i = 0; i < n; i++)//测试ind正确性
    {
        cout << g[i].val << " : " << ind[i]<< endl;
    }
    */

    for (int i = 0; i < n; i++)//找入度为0的顶点
    {
        if(ind[i] == 0)
        {
            q.push_back(i);
        }
    }
    for (int i = 0; i < n; i++)         //依次取点,刷新入度,直到取完n个点
    {
        if(q.empty())
        {
            break;
            cout<<"failed!\n";
        }
        topo[i] = q.front();
        q.pop();
        Edge* e = g[topo[i]].first;
        while(e)
        {
            ind[e->vexP]--;
            if(ind[e->vexP] == 0)       //有可能要加入的顶点
                q.push_back(e->vexP);
            e = e->next;
        }
    }
    delete[] ind ;
    ind = nullptr;
}
#pragma endregion

int main()
{
    int n,m;
    cin >> n >> m;
    Graph aov;
    aov.n = n;
    for (int i = 0; i < n; i++)
    {
        cin >> aov.g[i].val;
    }
    for (int i = 0; i < m; i++)
    {
        int a,b;
        char ca,cb;
        cin >> ca >> cb;
        a = aov.find(ca);
        b = aov.find(cb);
        aov.addEdge(a,b);
    }
    /*测试
    cout<<"----------------------------\n";
    for (int i = 0; i < n; i++)
    {
        cout << i <<" : " << aov.g[i].val << endl;
    }

    for (int i = 0; i < n; i++)
    {
        Edge* e = aov.g[i].first;
        while(e)
        {
            cout << aov.g[i].val << " -> " <<  aov.g[e->vexP].val <<endl;
            e = e->next;
        }
    }
    
    cout<<"----------------------------\n";
    */
    aov.getTopo();
    cout<< "topo sort result :\n";
    for (int i = 0; i < n; i++)
    {
        cout <<aov.g[aov.topo[i]].val <<' ';
    }
    cout<<endl;
}

输入例子

/*
6 8
A B C D E F
A B
A C
A D
C B
C E
D E
F E
F D
*/

输出结果

topo sort result :
A F C D B E

实例图示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值