本博文是是博主在学习数据结构图的这一章知识时做的一些总结,代码运行环境: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语言数据结构之图的基本操作的更多相关文章

  1. 【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)

    邻接矩阵实现如下: /* 主题:用邻接矩阵实现 DFS(递归) 与 BFS(非递归) 作者:Laugh 语言:C++ ***************************************** ...

  2. C++数据结构之图

    图的实现是一件很麻烦的事情,很多同学可能在学数据结构时只是理解了图的基本操作和遍历原理,但并没有动手实践过.在此,我说说我的实现过程. 首先,在草稿纸上画一个图表,这里是有向图,无向图也一样,如下: ...

  3. 数据结构之--图(Graphics)

    1.1:图的定义和术语   图是一种比线性表和树更为复杂的数据结构.在线性表中,数据元素之间仅有线性关系,每个元素仅有一个直接前驱和一个直接后继:在树形结构中,数据元素之间有着明显的层次关系,并且每一 ...

  4. 利用python+graphviz绘制数据结构关系图和指定目录下头文件包含关系图

    作为一名linux系统下的C语言开发,日常工作中经常遇到两个问题: 一是分析代码过程中,各种数据结构互相关联,只通过代码很难理清系统中所有结构体的整体架构,影响代码消化的效率; 二是多层头文件嵌套包含 ...

  5. python数据结构之图的实现

    python数据结构之图的实现,官方有一篇文章介绍,http://www.python.org/doc/essays/graphs.html 下面简要的介绍下: 比如有这么一张图: A -> B ...

  6. hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)

    还是畅通工程 Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

  7. python数据结构之图的实现方法

    python数据结构之图的实现方法 本文实例讲述了python数据结构之图的实现方法.分享给大家供大家参考.具体如下: 下面简要的介绍下: 比如有这么一张图:     A -> B     A ...

  8. python数据结构之图深度优先和广度优先实例详解

    本文实例讲述了python数据结构之图深度优先和广度优先用法.分享给大家供大家参考.具体如下: 首先有一个概念:回溯 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到 ...

  9. 数据结构(C语言)关于树、二叉树、图的基本操作。

    1) 编写算法函数int equal(tree t1, tree t2),判断两棵给定的树是否等价: int equal(tree t1,tree t2) { int k; if(t1==NULL&a ...

随机推荐

  1. mysql查询大于X分钟数

    select * from table where   date_add(STR_TO_DATE(createtime,'%Y-%m-%d %T:%i:%s'), interval '00:60:00 ...

  2. react-native 生命周期

    一.前言 问: 什么是组件的生命周期? 组件的生命周期中都包含哪些方法,各有什么作用? 生命周期的方法都在什么时候调用? 生命周期: 顾名思义,一个主体从出生到死亡的整个过程 学习组件(React的基 ...

  3. 自制精排 ePub 集、不定期更新(UPDATA-2015-8-2)

    说明 排版不说最好,上乘是必须的. 段落空行 首行缩进 具备清爽元数据 包含高清封面.目录 图片居中,图片标题以下标形式居中位于图片下* 支持多看/Kindle原生系统弹出注释,其他软件跳转注释* 各 ...

  4. How To Check Member In Window VS With CplusPlus?

    实例说明 下面这个实例代码, 快速举例了在Win32应用程序下,对于内存的泄漏检查. 其中的原理,目前本人还是不太的理解. 只是记录了使用方法. 以后,看情况,会更新的. #ifdef _WIN32 ...

  5. WSTMart商城系统数据字典

    欢迎来到WSTMart官网  开源多用户商城  QQ交流群: 返回首页|返回首页| 开发手册 | 数据库字典 | 授权查询 | 授权用户登录 | 官方微信扫一扫 x QQ客服 服务热线 020-852 ...

  6. JavaScript RegExp.exec() 方法

    定义和用法: exec() 方法用于检索字符串中的正则表达式的匹配. 语法: RegExpObject.exec(string); RegExpObject:必须参数,正则表达式: string:必须 ...

  7. 电脑清缓存(C盘占空间)

    电脑缓存目录: 1.取消文件隐藏 2.找到C:\Users\lwx351192\AppData\Local\Temp目录下的三个子文件夹local,locallow,roaming里面的文件都可删除, ...

  8. [Training Video - 1] [Selenium Basics] [Download and Install Selenium]

    Download Selenium Jars Configure jars in eclipse Webdriver http://docs.seleniumhq.org/download/ Sele ...

  9. Python中的排序方法sort(),sorted(),argsort()等

    python 列表排序方法sort.sorted技巧篇 转自https://www.cnblogs.com/whaben/p/6495702.html,学习参考. Python list内置sort( ...

  10. 在Eclipse中使用Struts和Hibernate框架搭建Maven Web项目

    前言 学习使用Java还是2012年的事情,刚开始学习的Java的时候,使用的是MyEclipse工具和SSH框架.初学者适合使用MyEclipse,因为他将struts.Spring和Hiberna ...