本博文是是博主在学习数据结构图的这一章知识时做的一些总结,代码运行环境: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. 30. Substring with Concatenation of All Words (String; HashTable)

    You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...

  2. 解决Springboot集成ActivitiModel提示输入用户名密码的问题

    一.原因分析 先要知道两点 - SpringBoot会根据引入的Jar包而自动配置相应的功能. - ActivitiModeler中引用了Spring Security的Jar.(是一个安全或者说权限 ...

  3. 4-在windon10上mysql安装与图形化管理

    安装及可能遇到的问题: 1.windows10上安装mysql(详细步骤  https://blog.csdn.net/zhouzezhou/article/details/52446608 2. 在 ...

  4. Ubuntu 安装配置 nginx

    作者:任明旭链接:https://www.zhihu.com/question/46241604/answer/100788789来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  5. 让Ubuntu使用阿里云国内源,解决下载速度慢问题。

    阿里云镜像官方地址 http://mirrors.aliyun.com/ 找到最新源地址列表: http://www.linuxdiyf.com/linux/23163.html 软件包管理中心(推荐 ...

  6. 在Linux下使用logrotate管理日志(转)

    原文地址:http://www.tuicool.com/articles/ieAnMjN logrotate是日志循环管理工具,可以分割日志文件,删除旧的日志文件,创建新的日志文件,循环管理日志从而节 ...

  7. SGU 194 Reactor Cooling (有容量和下界的可行流)

    题意:给定上一个有容量和下界的网络,让你求出一组可行解. 析:先建立一个超级源点 s 和汇点 t ,然后在输入时记录到每个结点的下界的和,建边的时候就建立c - b的最后再建立 s 和 t , 在建立 ...

  8. 利用JS判断浏览器版本

    function checkBrowser() { var browserName = navigator.userAgent.toLowerCase(); //var ua = navigator. ...

  9. [Selenium With C#基础教程] Lesson-03 超级链接

    作者:Surpassme 来源:http://www.jianshu.com/p/83809943e751 声明:本文为原创文章,如需转载请在文章页面明显位置给出原文链接,谢谢. 超级链接或链接是We ...

  10. CodeForces 572D Minimization(DP)

    题意翻译 给定数组AAA 和值kkk ,你可以重排AAA 中的元素,使得∑i=1n−k∣Ai−Ai+k∣\displaystyle\sum_{i=1}^{n-k} |A_i-A_{i+k}|i=1∑n ...