用队列实现图的拓扑排序

2023-05-16

#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 100      //最大顶点数
#define MAXSIZE 100 //数组最大长度
typedef char VertexType;     //顶点
typedef int EdgeType;   //权值
#define UNVISITED -1    //标记未访问
#define VISITED 1   //标记未访问
#define OK 1
#define ERROR 0

typedef int Status;
typedef int  QElemtype;
typedef struct
{
    QElemtype data[MAXSIZE];
    int front;
    int rear;
}sqQueue;


//队列的初始化
Status InitQueue(sqQueue * Q)
{
    Q->front=0;
    Q->rear=0;
    return OK;
}



//队列的长度
Status QueueLength(sqQueue Q)
{
    return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}



//入队操作
Status EnQueue(sqQueue * Q, QElemtype e)
{
    if((Q->rear+1)%MAXSIZE==Q->front)
    {
        return ERROR;
    }
    Q->data[Q->rear]=e;
    Q->rear=(Q->rear+1)%MAXSIZE;
    return OK;
}



//出队操作
Status DeQueue(sqQueue * Q,QElemtype * e)
{
    if(Q->front==Q->rear)
    {
        return ERROR;
    }
    *e=Q->data[Q->front];
    Q->front=(Q->front+1)%MAXSIZE;
    return OK;
}




//打印元素
void print(sqQueue * Q)
{
    int length=(Q->rear-Q->front+MAXSIZE)%MAXSIZE;
    for(int i=Q->front;i<length;i++)
    {
        printf("a[%d]=%d ,",i,Q->data[i]);
    }
    printf("\n");
}



//邻接表的存储结构
typedef struct
{
    int from;   //边的始点
    int to; //边的终点
    EdgeType weight;    //权重
}Edge;  //边的结构


typedef struct EdgeNode
{
    int adjvex; //该顶点对应的下标
    EdgeType weight;    //权重
    struct EdgeNode * next;
}EdgeNode;

typedef struct  //顶点结构
{
    VertexType data;
    EdgeNode * firstedge;
}VertexNode,AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numVertexes;
    int numEdges;
    int Indegree[MAXVEX];
    int Mark[MAXVEX];   //标记是否被访问过
}GraphAdjList;  //图结构


//初始化邻接表
void InitGraphAdjList(GraphAdjList * G,int numVer,int numEd)    //传入顶点数和边数
{
    G->numVertexes=numVer;
    G->numEdges=numEd;
    for(int i=0;i<G->numVertexes;i++)
    {
        G->Mark[i]=UNVISITED;
        G->Indegree[i]=0;
        G->adjList[i].firstedge=NULL;   //将边表置空表
    }
}


//创建一条边(有向图)
void Creat_Edge(GraphAdjList * G,int from,int to,int weight)
{
    EdgeNode * temp= G->adjList[from].firstedge;
    if(temp==NULL)
    {
        EdgeNode * NewEdgeNode=(EdgeNode *)malloc(sizeof(EdgeNode));
        NewEdgeNode->adjvex=to;
        NewEdgeNode->weight=weight;
        NewEdgeNode->next=NULL;
        G->adjList[from].firstedge=NewEdgeNode;
        G->Indegree[to]++;
    }
    else
    {
        while(temp->next!=NULL)
        {
            temp=temp->next;
        }
        EdgeNode * NewEdgeNode=(EdgeNode *)malloc(sizeof(EdgeNode));
        NewEdgeNode->adjvex=to;
        NewEdgeNode->weight=weight;
        NewEdgeNode->next=NULL;
        temp->next=NewEdgeNode;
        G->Indegree[to]++;

    }
}




/*建立图的邻接表结构(有向图)*/
void GreateALGraph(GraphAdjList * G)
{
    int i,j,k,w;
    printf("请输入%d个元素:\n",G->numVertexes);
    for(i=0;i<G->numVertexes;i++)   /*读入顶点信息,建立顶点表*/
    {
        scanf(" %c",&G->adjList[i].data);   /*输入顶点信息*/
        G->adjList[i].firstedge=NULL;   /*将边表置空表*/
    }
    for(k=0;k<G->numEdges;k++)  /*建立边表*/
    {
        printf("输入边(Vi,Vj)上的顶点序号和权重:\n");
        scanf("%d%d%d",&i,&j,&w);   /*输入(Vi,Vj)上的顶点序号*/
        Creat_Edge(G,i,j,w);
    }
}




//返回边表的第一条边
Edge FirstEdge(GraphAdjList * G,int oneVertex)
{
    Edge firstEdge;
    firstEdge.from=oneVertex;
    EdgeNode * temp=G->adjList[oneVertex].firstedge;
    if(temp!=NULL)
    {
        firstEdge.to=temp->adjvex;
        firstEdge.weight=temp->weight;
    }
    else
    {
        firstEdge.to=-1;
        firstEdge.weight=-1;
    }
    return firstEdge;
}




//返回oneEdge的终点
int ToVertex(Edge oneEdge)
{
    return oneEdge.to;
}




//返回与perEdge相同顶点的下一条边
Edge NextEdge(GraphAdjList * G,Edge perEdge)
{
    Edge myEdge;
    myEdge.from=perEdge.from;
    EdgeNode * temp=G->adjList[perEdge.from].firstedge;
    while(temp!=NULL && temp->adjvex<=perEdge.to)
    {
        temp=temp->next;
    }
    if(temp!=NULL)
    {
        myEdge.to=temp->adjvex;
        myEdge.weight=temp->weight;
    }
    else
    {
        myEdge.to=-1;
        myEdge.weight=-1;
    }
    return myEdge;
}


//判断是否为边
bool IsEdge(Edge oneEdge)
{
    if(oneEdge.to==-1 )
    {
        return false;
    }
    else
    {
        return true;
    }
}





//访问当前的顶点
void Vist(GraphAdjList * G,int v)
{
    printf("%c ",G->adjList[v]);
}



//用队列实现拓扑排序
void TopsortbyQueue(GraphAdjList * G,sqQueue * Q)
{
    int i;
    QElemtype Elem;
    for(i=0;i<G->numVertexes;i++)
    {
        G->Mark[i]=UNVISITED;
    }
    for(i=0;i<G->numVertexes;i++)
    {
        if(G->Indegree[i]==0)
        {
            EnQueue(Q, i);      
        }
    }
    while(QueueLength(*Q)!=0)   //如果队列不为空
    {
        DeQueue(Q,&Elem);
        printf("%c ",G->adjList[Elem].data);
        G->Mark[Elem]=VISITED;
        for(Edge e=FirstEdge(G,Elem);IsEdge(e);e=NextEdge(G,e))
        {
            G->Indegree[ToVertex(e)]--;
            if(G->Indegree[ToVertex(e)]==0)
            {
                EnQueue(Q, ToVertex(e));    
            }
        }
    }
    for(i=0;i<G->numVertexes;i++)
    {
        if(G->Mark[i]==UNVISITED)
        {
            printf("此图有环!\n");
            break;
        }
    }
}



int main()
{
    GraphAdjList  G;
    sqQueue Q;
    InitQueue(&Q);
    int numVer,numEd;
    printf("请输入顶点数和边数:\n");
    scanf("%d%d",&numVer,&numEd);
    InitGraphAdjList(&G,numVer,numEd);
    GreateALGraph(&G);
    TopsortbyQueue(&G,&Q);
    printf("\n");
    return 0;
}

这里写图片描述这里写图片描述
这里写图片描述
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用队列实现图的拓扑排序 的相关文章

  • Vue项目导入ElementUI后,网页无显示,打不开Vue的Main页面

    错误如下 xff0c 这是因为我们的vue版本和node js版本太高了 xff0c 我们需要使用Element plus 执行 cnpm install save element plus 然后字main js中修改 import Ele
  • 递归求n的阶乘完整版

    递归函数 求n的阶乘 span class token keyword def span span class token function fun span span class token punctuation span Num sp
  • Ubuntu基础使用指南

    一 基础操作 1 终端重要热键 Tab xff1a 补全功能 Ctrl 43 c xff1a 中断目前程序 Ctrl 43 d xff1a 键盘输入结束 Ctrl 43 Shift 43 c xff1a 复制 Ctrl 43 Shift 4
  • Fixed Frame [base_link] does not exist

    出现这个问题请先检查有没有启动gazebo xff0c gazebo是否能正常加载模型 如果不能 xff0c 那么rviz很可能也加载不了相应的节点 启动了gazebo xff0c 在Fixed frame后可以选择节点 xff0c 没有启
  • 舵机控制(0°与90°之间反复)

  • 1488 新的开始

    1488 新的开始 新的开始 保证最少的花费 xff0c 那么很明显这就是一个最小生成树了 做题之前盲猜一下 xff0c 这个题应该要跑两遍最小生成树 xff0c 因为他说了使用两种情况 xff0c p和v 在井上修建一个和在各个井中间修建
  • Rancher2.7 + Jenkins CI/CD全流程保姆级最佳实践

    Rancher 43 Jenkins k8s集群 CI CD全流程最佳实践 CI方面 xff0c 官方推荐的视频教程等多是使用极狐Gitlab CI xff0c 但社区版极狐每月仅400分钟构造时间 xff0c 额外购买价格为1000分钟
  • linux驱动----内核模块

    目录 一 引言 二 模块的特点 三 模块程序的构成 必要内容 1 模块入口函数 2 模块出口函数 3 模块许可证声明 非必要内容 1 模块参数 2 模块导出符号 3 模块相关信息 四 模块操作命令 一 引言 我们往往需要对内核的大小进行控制
  • linux驱动----模块符号导出使用

    本文介绍一种 xff0c 一个模块调动另一个模块中定义的函数的方法 在内核中 xff0c 函数又叫做符号 xff0c 为了便于理解 xff0c 此处说成我们在C语言中熟悉的函数调用 xff0c 回想一下C语言中的函数调用 xff0c 如果我
  • gcc的编译流程

    xff08 1 xff09 预处理阶段 xff08 c gt i xff09 预处理器会处理所有的以 开头的命令 xff0c 这些都属于预处理命令 xff0c 也就是会将所有的头文件包含的东西插入到源文件中 xff0c 将所有定义的宏都在程
  • Linux驱动----mmap系统调用

    在介绍mmap之前 xff0c 我们首先要了解 xff0c 如果没有mmap xff0c 在我们对一个设备进行操作时 xff0c 内核中其实有映射一份该设备的物理内存地址 xff0c 这是一份虚拟地址 xff0c 但是这是属于内核的 xff
  • STM32的启动流程

    本文主要介绍 xff0c STM32从 CPU 上电复位执行第 1 条指令开始 xff08 汇编文件 xff09 到进入 C 程序 main 函数入口之间的那个部分 基本流程如下 1 确定启动方式 每个STM32的芯片上都有两个管脚BOOT
  • 推挽输出&&开漏输出

    在学习STM32的时候 xff0c 我发现了一个很值得研究学习的问题 xff0c 下面 xff0c 用我的理解来阐述一遍 xff0c 这其中的原理 首先请看电路图 在给GPIO配置输出的时候 xff0c 其有两种工作模式可选 xff0c 分
  • const

    const是一个限定符 xff0c 被const限定的变量其值不会被改变 目录 1 修饰变量 2 修饰指针 3 修饰引用 4 修饰成员函数 5 宏定义 define 和 const 常量 1 修饰变量 指向的变量的值不可改变 xff0c 次
  • 用联合体(union)判断大小端

    1 联合体的概念 联合 xff08 union xff09 是一种节省空间的特殊的类 xff0c 一个 union 可以有多个数据成员 xff0c 但是在任意时刻只有一个数据成员可以有值 当某个成员被赋值后其他成员变为未定义状态 这是因为和
  • 字节对齐(结构体)

    直接从问题入手 xff0c 下面这个结构体 xff0c 占多大内存 xff0c 也就是求sizeof xff08 A xff09 是多少 struct A int a char b double c 这就涉及到一个字节对齐的问题 xff0c
  • mysql 8.0.12安装注意事项

    安装 使用msi方式安装 xff0c win10系统 问题 安装之后想使用命令行的方式 xff0c 不是mysql自带的mysql shell所产生的问题 xff1a mysql 不是内部或外部命令 xff0c 也不是可运行的程序或批处理文
  • 树莓派创建WiFi热点

    0x00 将代码clone到本地 git span class hljs keyword clone span https span class hljs comment github com oblique create ap span
  • 虚函数表和虚函数指针

    虚函数表 vtable 虚函数指针 vptr 虚函数表会出现在一个带有虚函数的类中 xff0c 是属于类的 虚函数表相当于一个数组 xff0c 其中存放的只有虚函数 xff0c 可以是继承而来的 xff0c 也可以是自己本身的 虚函数指针是
  • 在构造函数中使用虚函数可以实现多态吗?

    在构造函数和析构函数中使用虚函数可以实现多态吗 xff1f 不能 因为不管是构造函数还是析构函数 xff0c 其父类和子类的执行都是有一定顺序的 xff0c 拿构造函数来说 xff0c 父类的构造函数会先生成 xff08 一个很简单的道理

随机推荐

  • C++类型转换操作符

    在C语言中其实已有类型转换 xff0c 比如强制类型转换 xff0c 形式上是 type expression 对标C中的强制类型转换 xff0c C 43 43 中按照类型转换的意图对他们进行了分类 xff0c 形式上是 static c
  • 直接插入法排序

    本文试例在VS编译器下可正常使用 算法思想 xff1a 每次从待排序的原始序列中取出一个元素 xff0c 将其排入一个新的有序数列中 xff0c 这实际上是一个有序子序列不断增长的过程 xff0c 当有序子序列与原序列的长度一致时 xff0
  • 编译器的差别gcc和VS

    问题的由来是我写了一个排序算法程序 xff0c 在gcc编译器下运行 xff0c 发现结果有问题 xff0c 然后开展的寻找错误解决问题 这是我写的一个简单的插入排序算法 include lt stdio h gt 直接插入法排序函数主体
  • 计算机程序内存分布

    计算机存储器 计算机中有两种存储器 xff0c RAM和ROM RAM xff1a 随机存取存储器 xff08 random access memory xff09 xff0c 也叫主存 内存 它可以随时读写 xff0c 而且速度很快 xf
  • linux下的线程thread

    何为线程 xff1f 线程是一种轻量级的进程 xff0c 一个进程至少包含 1 个线程 xff0c 也可以包含多个线程 xff0c 所有线程共享进程的资源 xff0c 各个线程也可以拥有属于自己的私有资源 其实 xff0c 进程仅负责为各个
  • 线程同步的实现

    互斥锁 互斥锁的使用就是当有线程访问进程空间中的公共资源时 xff0c 线程执行 加锁 操作 将资源锁起来 xff0c 阻止其它线程的访问 访问完成后 xff0c 该线程 xff08 谁锁上的必须由谁来解锁 xff09 负责完成 解锁 操作
  • TCP粘包问题

    TCP是一种可靠 顺序 耗资的传输协议 xff0c UDP则反之 关于TCP的粘包问题 首先 xff0c 关于传输层协议中的TCP和UDP两种协议 xff0c 其中只有TCP会出现这个沾包的问题 xff0c 因为 xff0c TCP是流式套
  • 如何在shell脚本中使用环境变量的值

    1 问题的由来 此处展示的是脚本的一部分 if Update mode eq 0 then TF update else UDS update fi 说明 xff1a Update mode是一个环境变量 xff0c TF update和U
  • clang-format格式文件。可以直接复制引用

    Language Cpp BasedOnStyle LLVM AccessModifierOffset 2 AlignAfterOpenBracket Align AlignConsecutiveMacros false AlignCons
  • 环形缓冲区(c语言)

    1 概念介绍 在我们需要处理大量数据的时候 xff0c 不能存储所有的数据 xff0c 只能先处理先来的 xff0c 然后将这个数据释放 xff0c 再去处理下一个数据 如果在一个线性的缓冲区中 xff0c 那些已经被处理的数据的内存就会被
  • JAVA基础06——运算符02

    1 位运算 处理数据类型的时候 xff0c 可以直接对组成整形数值的各个位完成操作 amp 34 and 34 34 or 34 xff08 34 not 34 xff09 34 xor 以下用例皆为byte类型 xff1a xff1a 按
  • TCP/IP协议学习笔记(五)Windows下多线程多客户端的TCP服务端的实现

    使用多线程来实现可与多个客户端通信的服务端 当客户端连接上服务端之后 xff0c 为该客户端创建一个新的线程 xff0c 在该线程中与客户端进行通信 服务端程序中的主线程负责监听并接受客户端的连接请求 xff0c 创建与客户端通信的线程 另
  • docker tomcat ,把webapps.dist里面的全部文件 复制到 webapps下面就行。

    docker tomcat xff0c 把webapps dist里面的全部文件 复制到 webapps下面就行 cp r webapps dist webapps
  • ffmpeg 视频合并,无声或音视不同步

    无声 xff1a 第一个视频无声 xff0c 合并之后整个视频无声 例如上面是我用图片合成的视频 xff0c 就是没有音频的视频 只要没有音频的视频放在最前面 xff0c 那么整个视频都会没有声音 xff0c ffmpeg默认以第一个视频为
  • week4实验A 咕咕东的奇遇(字母圆环)

    题目 xff1a 咕咕东是个贪玩的孩子 有一天 xff0c 他从上古遗迹中得到了一个神奇的圆环 这个圆环由字母表组成首尾相接的环 xff0c 环上有一个指针 最初指向字母a 咕咕东每次可以顺时针或者逆时针旋转一格 例如 a顺时针旋转到z x
  • week13 作业C HDU-1176

    题目 xff1a 在大家不辞辛劳的帮助下 xff0c TT 顺利地完成了所有的神秘任务 神秘人很高兴 xff0c 决定给 TT 一个奖励 xff0c 即白日做梦之捡猫咪游戏 捡猫咪游戏是这样的 xff0c 猫咪从天上往下掉 xff0c 且只
  • week13作业B TT的神秘任务2

    题目 xff1a 在你们的帮助下 xff0c TT 轻松地完成了上一个神秘任务 但是令人没有想到的是 xff0c 几天后 xff0c TT 再次遇到了那个神秘人 而这一次 xff0c 神秘人决定加大难度 xff0c 并许诺 TT xff0c
  • week14作业B Q老师与十字叉

    Input 9 5 5 3 4 4 3 5 5 1 4 5 5 5 3 3 3 4 4 Output 0 0 0 0 0 4 1 1 2 记录每一行 每一列空白的格子数目 xff0c 然后遍历每一个格子 xff0c
  • week14 作业D Q老师染砖

    衣食无忧的 Q老师 有一天突发奇想 xff0c 想要去感受一下劳动人民的艰苦生活 具体工作是这样的 xff0c 有 N 块砖排成一排染色 xff0c 每一块砖需要涂上红 蓝 绿 黄这 4 种颜色中的其中 1 种 且当这 N 块砖中红色和绿色
  • 用队列实现图的拓扑排序

    span class hljs preprocessor include lt stdio h gt span span class hljs preprocessor include lt stdlib h gt span span cl