用邻接链表和队列实现拓扑排序

5 篇文章 0 订阅

之前写拓扑排序是通过邻接矩阵写的,应对小的数据量还可以,但要是顶点数很大时,开的邻接矩阵就未免太大了.今天学习了用邻接表实现拓扑排序,比较简单,所幸,写完后一遍编译通过 + 一遍AC.

**描述**
给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前

**输入**
若干行整数,第一行有2个数,分别为顶点数v和弧数a,接下来有a行,每一行有2个数,分别是该条弧所关联的两个顶点编号

**输出**
若干个空格隔开的顶点构成的序列(用小写字母)



**样例输入**
6 8
1 2
1 3
1 4
3 2
3 5
4 5
6 4
6 5

**样例输出**
v1 v3 v2 v6 v4 v5
//用邻接链表实现拓扑排序
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;

struct node//邻接表里的每个元素是一个结构体
{
    int num;
    node *next;
    node(){
        next = NULL;
    }
    node(int x):num(x){
        next = NULL;
    }
};

struct list
{
    int num;
    node *next;
    void append(node *&a)
    {
        a->next = next;//将a插到表头里去
        next = a;
    }
}point[2000];

int v, a;//顶点数,边数
int from, to;
int vis[2000], indeg[2000];

int main()
{
    queue<int> q;
    scanf("%d%d",&v,&a);
    while(a--)
    {
        scanf("%d%d",&from,&to);
        indeg[to]++;
        node *tmp = new node(to);
        point[from].append(tmp);//连接有向图
    }
    for(int i=1;i<=v;i++)
        if(indeg[i] == 0)
        {
            q.push(i);
            vis[i] = 1;
            break;
        }
    while(! q.empty())
    {
        int temp = q.front();
        q.pop();
        printf("v%d ",temp);
        node *t = point[temp].next;
        while(t)
        {
            indeg[t->num]--;
            t = t->next;
        }
        for(int i=1;i<=v;i++)//要求从小到大输出,所以每次从小到大遍历
            if(indeg[i]==0 && vis[i]==0)
            {
                vis[i] = 1;
                q.push(i);
                break;
            }
    }
    return 0;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是 C 语言实现采用队列完成拓扑排序算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_NODE 100 int in_degree[MAX_NODE]; // 记录每个节点的入度 int queue[MAX_NODE]; // 队列 int front = -1, rear = -1; // 队列的头尾指针 // 邻接表表示 struct Node { int data; struct Node* next; }; struct Graph { int num_nodes; // 节点数 struct Node** adj_list; // 邻接表 }; // 创建节点 struct Node* create_node(int data) { struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); new_node->data = data; new_node->next = NULL; return new_node; } // 添加边 void add_edge(struct Graph* graph, int src, int dest) { struct Node* new_node = create_node(dest); new_node->next = graph->adj_list[src]; graph->adj_list[src] = new_node; } // 初始化入度为 0 void init_in_degree(int* in_degree, int num_nodes) { for (int i = 0; i < num_nodes; i++) { in_degree[i] = 0; } } // 统计每个节点的入度 void count_in_degree(struct Graph* graph, int* in_degree) { for (int i = 0; i < graph->num_nodes; i++) { struct Node* temp = graph->adj_list[i]; while (temp != NULL) { in_degree[temp->data]++; temp = temp->next; } } } // 将节点加入队列 void enqueue(int* queue, int* rear, int node) { queue[++(*rear)] = node; } // 从队列中取出节点 int dequeue(int* queue, int* front) { return queue[++(*front)]; } // 实现拓扑排序 void topological_sort(struct Graph* graph) { int num_nodes = graph->num_nodes; init_in_degree(in_degree, num_nodes); // 初始化入度为 0 count_in_degree(graph, in_degree); // 统计每个节点的入度 // 将所有入度为 0 的节点加入队列 for (int i = 0; i < num_nodes; i++) { if (in_degree[i] == 0) { enqueue(queue, &rear, i); } } int count = 0; // 记录输出的节点数 while (front != rear) { // 队列非空 int node = dequeue(queue, &front); // 取出队首节点 printf("%d ", node); count++; // 将所有指向的节点的入度减 1,如果入度为 0,则加入队列 struct Node* temp = graph->adj_list[node]; while (temp != NULL) { in_degree[temp->data]--; if (in_degree[temp->data] == 0) { enqueue(queue, &rear, temp->data); } temp = temp->next; } } if (count != num_nodes) { // 输出的节点数小于节点总数,则说明存在环 printf("\n中存在环\n"); } } int main() { struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph)); graph->num_nodes = 6; graph->adj_list = (struct Node**)malloc(graph->num_nodes * sizeof(struct Node*)); for (int i = 0; i < graph->num_nodes; i++) { graph->adj_list[i] = NULL; } add_edge(graph, 0, 1); add_edge(graph, 0, 2); add_edge(graph, 1, 3); add_edge(graph, 2, 3); add_edge(graph, 2, 4); add_edge(graph, 3, 5); add_edge(graph, 4, 5); printf("拓扑排序结果:"); topological_sort(graph); return 0; } ``` 在上述代码中,我们定义了一个 `Graph` 结构体来表示有向,其中包含节点数和邻接表。在 `add_edge` 函数中,我们使用链表来存储每个节点指向的节点。在 `topological_sort` 函数中,我们使用队列来记录入度为 0 的节点,并按照拓扑排序的规则输出节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值