本博文是是博主在学习数据结构图的这一章知识时做的一些总结,代码运行环境: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. Jquery的树插件jqxTreeGrid的使用小结(实现基本的增删查改操作)

    一.引入相应的js <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" t ...

  2. asp.net页如何获取母版页控件

    获取母版页的相关内容有两种方法 1 通过findcontrol找控件ID需要在此事件中~因为Page_load中时是先内容页加载然后才是母版页加载 protected void Page_LoadCo ...

  3. merage语句

    MERGE  INTO  [credit].[record_rule_data] AS a  USING @tem AS b  ON  a.user_gid =@userLogGid  AND a.r ...

  4. 最多有k个不同字符的最长子字符串 · Longest Substring with at Most k Distinct Characters(没提交)

    [抄题]: 给定一个字符串,找到最多有k个不同字符的最长子字符串.eg:eceba, k = 3, return eceb [暴力解法]: 时间分析: 空间分析: [思维问题]: 怎么想到两根指针的: ...

  5. Java程序设计11——GUI设计与事件处理A

    1.GUI设计 Java使用AWT和Swing类完成图形用户界面编程,AWT全称是Abstract Window Toolkit,即抽象窗口工具集,它是Sun最早提供的GUI库,只是这个库功能比较有限 ...

  6. Android Studio修改默认Activity继承AppCompatActivity

    在Android Studio中新建Activity默认继承AppCompatActivity,感觉这点十分不爽,找了很久,终于发现在android Studio安装目录下有个模板文件,修改其中的参数 ...

  7. SpringBoot里的一些注解

    Spring不仅可以通过xml配置获取*.properties,还可以通过@Value注解的方式来获取,将properties配置文件中的属性值注入到java成员变量. 如果不想每次都写private ...

  8. AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务-(个人拙笔)(转)

    出处:http://www.bubuko.com/infodetail-827612.html AspNet.WebAPI.OData.ODataPQ 这是针对 Asp.net WebAPI ODat ...

  9. Java Annotation Processors

    Table Of Contents 1. Introduction 2. When to Use Annotation Processors 3. Annotation Processing Unde ...

  10. OpenGl中的Nurbs B样条曲面绘制

    NURBS 贝塞尔曲线的缺点是当我们增加很多控制点的时候,曲线变得不可控,其连续性会变差差.如果控制点很多(高阶曲线),当我们调整一个控制点的位置,对 整个曲线的影响是很大的.要获得更高级的控制,可以 ...