C语言数据结构之图的基本操作
本博文是是博主在学习数据结构图的这一章知识时做的一些总结,代码运行环境:visual studio2017 纯C语言 ,当然掌握了方法,你也可以试着用其它的语言来实现同样的功能。
下面的程序主要实现了对有向图,有向网,无向图,无向网,无向图的深度优先遍历,广度优先遍历,有向无环图的拓扑排序功能等。
主要代码实现如下:
- #pragma once
- #include<stdio.h>
- #include"stdlib.h"
- #define ElemType char
- #define MAXQSIZE 50
- #define INFINITY INT_MAX
- #define MAX_VERTEX_NUM 20
- typedef enum { DG, DN, UDG, UDN } GraphKind;
- typedef struct ArcCell {
- int adj; //顶点关系类型 对于无权图 用0或1表示
- //char *info; //弧相关信息的指针
- }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
- typedef struct {
- char vers[MAX_VERTEX_NUM]; //用一个字符数组存储顶点向量
- AdjMatrix arcs; //邻接矩阵
- int vexnum, arcnum; //图的当前顶点数和弧数
- GraphKind kind; //图的种类标志
- int in[MAX_VERTEX_NUM]; //存放所有节点的入度
- }MGraph;
- //图G中顶点v的第一个邻接点,不存在时返回 -1
- int FirstAdjVex(MGraph&G, int v)
- {
- int i;
- for (i = ; i < G.vexnum; i++)
- {
- if (G.arcs[v][i].adj)
- {
- return i;
- }
- }
- return -;
- }
- //图G中顶点v在w之后的下一个邻接点,不存在时返回 -1
- int NextAdjVex(MGraph G, int v, int w)
- {
- int i;
- for (i = w + ; i < G.vexnum; i++)
- {
- if (G.arcs[v][i].adj)
- {
- return i;
- }
- }
- return -;
- }
- //深度优先遍历图
- bool visited[MAX_VERTEX_NUM];
- void DFS(MGraph G, int v)
- {
- visited[v] = true;
- printf("%c", G.vers[v]);
- int j;
- for (j = ; j <= G.vexnum; j++) {
- if (visited[j] == && G.arcs[v][j].adj == )
- {
- DFS(G, j);//v每循环一次值都会变 上一轮的j值赋给了v
- }
- }
- }
- //广度优先遍历
- int BFSTraverse(MGraph G, int s)
- {
- //清空访问标志
- for (int i = ; i <MAX_VERTEX_NUM; i++)
- visited[i] = false;
- //定义队列,用于保存当前节点的邻接顶点
- int Q[MAX_VERTEX_NUM];
- int front = ;
- int rear = ;
- int i, j;
- printf("%c", G.vers[s]);
- visited[s] = ;
- Q[rear++] = s;
- //遍历队列
- while (front < rear)
- {
- i = Q[front++];
- for (j = ; j <= G.vexnum; j++)
- {
- if (visited[j] == false && G.arcs[i][j].adj == )
- {
- printf("%c", G.vers[j]);
- visited[j] = true;
- Q[rear++] = j;
- }
- }
- }
- return ;
- }
- //定位顶点
- int LocateVex(MGraph &G, char v)
- {
- int i;
- for (i = ; i<G.vexnum; i++)
- {
- if (v == G.vers[i])
- {
- return i;
- }
- }
- return -;
- }
- //创建有向图
- int CreateDG(MGraph &G) {
- int i, j, k;
- char v1, v2;
- printf("请输入顶点数:");
- scanf("%d", &G.vexnum);
- printf("\n请输入弧数:");
- scanf("%d", &G.arcnum);
- printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
- fflush(stdin);
- getchar(); //吃掉空格
- for (i = ; i < G.vexnum; i++)
- {
- scanf("%c", &G.vers[i]);
- getchar(); //吃掉空格 注意数组vers[i]的初始大小为20
- }
- //打印输出各个顶点
- for (i = ; i < G.vexnum; i++)
- {
- printf("%c", G.vers[i]);
- }
- printf("\n");
- for (i = ; i < G.vexnum; i++)
- {
- for (j = ; j < G.vexnum; j++)
- {
- G.arcs[i][j].adj = INFINITY;
- }
- }
- //入度初始化
- for (int i = ; i < G.vexnum; i++)
- {
- G.in[i] = ;
- }
- for (k = ; k < G.arcnum; k++)
- {
- printf("\nplease input <v1 v2>:");
- fflush(stdin);
- scanf("%c %c", &v1, &v2); //v1 v2 之间用空格隔开
- fflush(stdin);//清除残余后,后面再读入时不会出错
- i = LocateVex(G, v1);
- j = LocateVex(G, v2);
- G.arcs[i][j].adj = ;
- G.in[j]++;
- getchar();
- }
- return ;
- }
- //创建有向网
- int CreateDN(MGraph &G) {
- int i, j, k, w;
- char v1, v2;
- printf("请输入顶点数:");
- scanf("%d", &G.vexnum);
- printf("\n请输入弧的数目:");
- scanf("%d", &G.arcnum);
- printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
- fflush(stdin);
- getchar(); //吃掉空格
- for (i = ; i < G.vexnum; i++)
- {
- scanf("%c", &G.vers[i]);
- getchar(); //吃掉空格 注意数组vers[i]的初始大小为20
- }
- //打印输出各个顶点
- for (i = ; i < G.vexnum; i++)
- {
- printf("%c", G.vers[i]);
- }
- printf("\n");
- //初始化邻接矩阵
- for (i = ; i < G.vexnum; i++)
- {
- for (j = ; j < G.vexnum; j++)
- {
- G.arcs[i][j].adj = INFINITY;
- }
- }
- for (k = ; k < G.arcnum; k++)
- {
- printf("\n please input <v1 v2 w>:");
- fflush(stdin);
- scanf("%c %c %d", &v1, &v2, &w); //v1 v2 w之间用空格隔开
- fflush(stdin);//清除残余后,后面再读入时不会出错
- i = LocateVex(G, v1);
- j = LocateVex(G, v2);
- G.arcs[i][j].adj = w;
- getchar(); //吃掉空格
- }
- return ;
- }
- //创建无向图
- int CreateUDG(MGraph &G)
- {
- int i, j, k;
- char v1, v2;
- printf("请输入顶点数:");
- scanf("%d", &G.vexnum);
- printf("\n请输入边数:");
- scanf("%d", &G.arcnum);
- printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
- fflush(stdin);
- getchar(); //吃掉空格
- for (i = ; i < G.vexnum; i++)
- {
- scanf("%c", &G.vers[i]);
- getchar(); //吃掉空格 注意数组vers[i]的初始大小为20
- }
- //打印输出各个顶点
- for (i = ; i < G.vexnum; i++)
- {
- printf("%c", G.vers[i]);
- }
- printf("\n");
- for (i = ; i < G.vexnum; i++)
- {
- for (j = ; j < G.vexnum; j++)
- {
- G.arcs[i][j].adj = INFINITY;
- }
- }
- for (k = ; k < G.arcnum; k++)
- {
- printf("\nplease input <v1 v2>:");
- fflush(stdin);
- scanf("%c %c", &v1, &v2); //v1 v2 之间用空格隔开
- fflush(stdin);//清除残余后,后面再读入时不会出错
- i = LocateVex(G, v1);
- j = LocateVex(G, v2);
- G.arcs[i][j].adj = ;
- G.arcs[j][i].adj = ;
- getchar();
- }
- return ;
- }
- //创建无向网
- int CreateUDN(MGraph &G)
- {
- int i, j, k, w;
- char v1, v2;
- printf("请输入顶点数:");
- scanf("%d", &G.vexnum);
- printf("\n请输入边的数目:");
- scanf("%d", &G.arcnum);
- printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
- fflush(stdin);
- getchar(); //吃掉空格
- for (i = ; i < G.vexnum; i++)
- {
- scanf("%c", &G.vers[i]);
- getchar(); //吃掉空格 注意数组vers[i]的初始大小为20
- }
- //打印输出各个顶点
- for (i = ; i < G.vexnum; i++)
- {
- printf("%c", G.vers[i]);
- }
- printf("\n");
- //初始化邻接矩阵
- for (i = ; i < G.vexnum; i++)
- {
- for (j = ; j < G.vexnum; j++)
- {
- G.arcs[i][j].adj = INFINITY;
- }
- }
- for (k = ; k < G.arcnum; k++)
- {
- printf("\n please input <v1 v2 w>:");
- fflush(stdin);
- scanf("%c %c %d", &v1, &v2, &w); //v1 v2 w之间用空格隔开
- fflush(stdin);//清除残余后,后面再读入时不会出错
- i = LocateVex(G, v1);
- j = LocateVex(G, v2);
- G.arcs[i][j].adj = w;
- G.arcs[j][i].adj = w;
- getchar(); //吃掉空格
- }
- return ;
- }
- //栈类型
- typedef int SElemType;
- #define STACK_INIT_SIZE1 10 //存储空间初始分配量
- #define STACKINCREMENT1 2 //存储空间分配增量
- //栈的顺序存储结构表示
- typedef struct SqStack1
- {
- SElemType *base; //基地址
- SElemType *top; //栈顶指针
- int stacksize1; //当前已经分配的存储空间
- }SqStack1;
- //构造一个空栈
- int InitStack1(SqStack1&S)
- {
- //为栈底分分配一个指定大小的存储空间
- S.base = (SElemType *)malloc(STACK_INIT_SIZE1 * sizeof(SElemType));
- if (!S.base)
- exit();
- S.top = S.base; //栈底与栈顶指针相同
- S.stacksize1 = STACK_INIT_SIZE1;
- return ;
- }
- //若栈S为空栈(栈底指针和栈顶指针相同), 则返回1,否则返回0
- int StackEmpty1(SqStack1&S)
- {
- if (S.top == S.base)
- return ;
- else
- return ;
- }
- //插入元素e为新的栈顶元素
- int Push(SqStack1 *S, SElemType e)
- {
- if ((*S).top - (*S).base >= (*S).stacksize1)
- {
- (*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize1 + STACKINCREMENT1) * sizeof(SElemType));
- if (!(*S).base)
- exit();
- (*S).top = (*S).base + (*S).stacksize1;
- (*S).stacksize1 += STACKINCREMENT1;
- }
- *((*S).top)++ = e;
- return ;
- }
- //若栈不为空,则删除S栈顶元素用e返回其值,并返回1,否则返回0
- int Pop(SqStack1 *S, SElemType *e)
- {
- if ((*S).top == (*S).base)
- {
- return ;
- }
- *e = *--(*S).top;
- return ;
- }
- //有向图的拓扑排序
- void TopologicalSort(MGraph G)
- {
- int i, j,k;
- int count = ;
- SqStack1 S;
- InitStack1(S);
- for (i = ; i<G.vexnum; i++)
- {
- if (G.in[i] == )
- {
- Push(&S, i);
- }
- }
- while (!StackEmpty1(S))
- {
- Pop(&S, &k);
- printf("%c->", G.vers[k]);
- count++;
- for (i = ; i < G.vexnum; i++)
- {
- if (G.arcs[k][i].adj == )
- {
- G.in[i]--;
- if (G.in[i] == )
- {
- Push(&S, i);
- }
- }
- }
- }
- //如果计算得到的拓扑排序的节点数目小于总的,说明不是连通图
- if (count < G.vexnum)
- {
- printf("此图是有环路的\n");
- }
- else
- {
- printf("此图是没有环路的\n");
- }
- }
C语言数据结构之图的基本操作的更多相关文章
- 【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)
邻接矩阵实现如下: /* 主题:用邻接矩阵实现 DFS(递归) 与 BFS(非递归) 作者:Laugh 语言:C++ ***************************************** ...
- C++数据结构之图
图的实现是一件很麻烦的事情,很多同学可能在学数据结构时只是理解了图的基本操作和遍历原理,但并没有动手实践过.在此,我说说我的实现过程. 首先,在草稿纸上画一个图表,这里是有向图,无向图也一样,如下: ...
- 数据结构之--图(Graphics)
1.1:图的定义和术语 图是一种比线性表和树更为复杂的数据结构.在线性表中,数据元素之间仅有线性关系,每个元素仅有一个直接前驱和一个直接后继:在树形结构中,数据元素之间有着明显的层次关系,并且每一 ...
- 利用python+graphviz绘制数据结构关系图和指定目录下头文件包含关系图
作为一名linux系统下的C语言开发,日常工作中经常遇到两个问题: 一是分析代码过程中,各种数据结构互相关联,只通过代码很难理清系统中所有结构体的整体架构,影响代码消化的效率; 二是多层头文件嵌套包含 ...
- python数据结构之图的实现
python数据结构之图的实现,官方有一篇文章介绍,http://www.python.org/doc/essays/graphs.html 下面简要的介绍下: 比如有这么一张图: A -> B ...
- hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)
还是畅通工程 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- python数据结构之图的实现方法
python数据结构之图的实现方法 本文实例讲述了python数据结构之图的实现方法.分享给大家供大家参考.具体如下: 下面简要的介绍下: 比如有这么一张图: A -> B A ...
- python数据结构之图深度优先和广度优先实例详解
本文实例讲述了python数据结构之图深度优先和广度优先用法.分享给大家供大家参考.具体如下: 首先有一个概念:回溯 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到 ...
- 数据结构(C语言)关于树、二叉树、图的基本操作。
1) 编写算法函数int equal(tree t1, tree t2),判断两棵给定的树是否等价: int equal(tree t1,tree t2) { int k; if(t1==NULL&a ...
随机推荐
- 线程并发线程安全介绍及java.util.concurrent包下类介绍
线程Thread,在Java开发中多线程是必不可少的,但是真正能用好的并不多! 首先开启一个线程三种方式 ①new Thread(Runnable).start() ②thread.start(); ...
- Jdeveloper下Svn的使用
Jdeveloper下Svn的使用 官方pdf:jdeveloper使用svn 官方网地址:http://www.oracle.com/technetwork/cn/java/subversion-0 ...
- php识别二维码
php-zbarcode 是 PHP 读取条形码的扩展模块,目前仅支持 php5.x
- WEB开发常见错误-php无法操作数据库
Ubuntu 安装phpmyadmin 和配置 ubuntu 安装 phpmyadmin 两种 : 1: apt-get 安装 然后使用 已有的虚拟主机目录建立软连接 sudo apt-g ...
- 如何在Github上删除项目及某个文件
在Github上删除项目 在GitHub仓库中找到已经建立好的某个仓库,本篇文章以我的myBookCodes仓库为例,在建立的myBookCodes仓库中首先找到settings选项,如图所示: 将页 ...
- CentOS 6.6 MySQL 8.0详细安装步骤
1.备份服务器上MySQL数据库 [root@localhost ] # mysqldump -h localhost -u root -proot --databases Surpass --rou ...
- [转]How to Clean the Global Assembly Cache
本文转自:https://www.techwalla.com/articles/how-to-clean-the-global-assembly-cache The Global Assembly C ...
- 洛谷 P1967 货车运输(克鲁斯卡尔重构树)
题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...
- Linux文件扩展思考随笔
Linux文件时间 ============================================================ ls -l 文件名 仅看到的是最后被修改的时间 Linux ...
- NativeScript的开发体会
上个月开始,国内的主流技术网站开始在推荐NativeScrpit,"js+xml写跨终端app"."原生体验挡不住",很多网站都拿这个当做宣传NativeScr ...