C语言数据结构图的创建与遍历实验示例

 更新时间:2022年06月06日 17:28:21   作者:拆掉思维的墙  
这篇文章主要为大家介绍了C语言数据结构图的创建与遍历实验示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、 实验目的

理解图的基本概念,掌握图的存储结构,实现图的深度优先搜索遍历算法与广度优先搜索遍历算法。

二、 实验内容

利用邻接矩阵描述示例图,编写程序输出示例图的深度优先搜索和广度优先搜索的遍历序列。

具体步骤如下:

  • 将图的邻接矩阵描述为一个二维数组,并将该数组定义为全局变量,以便数据的传递;
  • 定义一个队列,在广度优先搜索时,该队列存储已被访问的路径长度为1,2,…的顶点;
  • 定义访问函数visit()、深度优先搜索函数DFS()和广度优先搜索函数BFS();
  • 主函数实现各函数的调用。

三、 实验工具

Dev-C++

四、 实验代码

//Authors:xiaobei
#include<stdio.h>
#include<stdlib.h>
#define MaxInt 32767
#define MVNum 100
typedef char VerTexType;
typedef int ArcType;
//定义图结构
typedef struct{
 VerTexType vexs[MVNum];
 ArcType arcs[MVNum][MVNum];
 int vexnum,arcnum;
}AMGraph;
//定义辅助链队
typedef struct QNode{
 char data;
 struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
 QueuePtr front;
 QueuePtr rear;
}LinkQueue;
//定义全局辅助数组visited[MVNum]
int visited[MVNum];
//函数返回定点下标
int LocateVex(AMGraph G,char v){
 int i;
 for(i=0;i<G.vexnum;i++)
  if(G.vexs[i]==v)
   return i;
  return -1;
}
//函数访问并输出顶点,返回下标
int visit(AMGraph G,char v){
 int i;
 for(i=0;i<G.vexnum;i++)
  if(v==G.vexs[i])
   printf("%c",v);
 return LocateVex(G,v);
}
//函数创建无向图,以邻接矩阵形式
int CreateUDN(AMGraph &G){
 int i,j,k,v1,v2,w;
 printf("[输入总顶点数和边数:]\n>>>");
 scanf("%d %d",&G.vexnum,&G.arcnum);
 for(i=0;i<G.vexnum;i++)
 {
  getchar();
  printf("[依次输入各顶点的信息:]\n>>>");
  scanf("%c",&G.vexs[i]);
 }
 for(i=0;i<G.vexnum;i++)
  for(j=0;j<G.vexnum;j++)
   G.arcs[i][j] = MaxInt;
 for(k=0;k<G.arcnum;k++){
  getchar();
  printf("[输入一条边依附的顶点及权值:]\n>>>"); 
  scanf("%c %c %d",&v1,&v2,&w);
  i = LocateVex(G,v1);
  j = LocateVex(G,v2);
  G.arcs[i][j]=w;
  G.arcs[j][i]=G.arcs[i][j];
 }
 return 1;
}
//函数深度遍历连通图
void DFS_AM(AMGraph G,char v){
 int w,u;
 u = visit(G,v);
 visited[u] = 1;
 for(w=0;w<G.vexnum;w++){
  if((G.arcs[u][w]<MaxInt) && (!visited[w]))
   DFS_AM(G,G.vexs[w]);
 }
}
//函数初始化链队
void InitQueue(LinkQueue &Q){
 Q.front = Q.rear = (QNode*)malloc(sizeof(QNode));
 Q.front->next=NULL;
}
//函数数据进队
void EnQueue(LinkQueue &Q,char e){
 QueuePtr p;
 p = (QNode*)malloc(sizeof(QNode));
 p->data = e;
 p->next = NULL;
 Q.rear->next=p;
 Q.rear = p;
}
//函数数据出队
void DeQueue(LinkQueue &Q,char &e){
 QueuePtr p;
 if(Q.front==Q.rear);
 else
 {
  p = Q.front->next;
  e = p->data;
  Q.front->next = p->next;
  if(Q.rear==p)
   Q.rear=Q.front;
  free(p);
 }
}
//函数判断链队是否为空
int QueueEmpty(LinkQueue Q){
 if(Q.front==Q.rear)
  return 1;
 else
  return 0;
}
//函数返回顶点下一个邻接点下标
int FirstAdjVex(AMGraph G,int c){
 int j;
 for(j=0;j<G.vexnum;j++)
  if(G.arcs[c][j]<MaxInt && visited[j]==0)
   return j;
  return -1;
}
//函数返回顶点下一个相对邻接点下标
int NextAdjVex(AMGraph G,int c,int w){
 int j;
 for(j=0;j<G.vexnum;j++)
  if(G.arcs[c][j]<MaxInt && visited[j]==0)
   return j;
  return -1;
}
//函数广度遍历连通图
void BFS_AM(AMGraph G,char v){
 int c,w,i;
 char u;
 LinkQueue Q;
 c = visit(G,v);
 visited[c] = 1;
 InitQueue(Q);
 EnQueue(Q,v);
 while(!QueueEmpty(Q)){
  DeQueue(Q,u);
  c = LocateVex(G,u);
  for(w=FirstAdjVex(G,c);w>=0;w=NextAdjVex(G,c,w))
  {
   if(!visited[w]){
    i = visit(G,G.vexs[w]);
    visited[i] = 1;
    EnQueue(Q,G.vexs[w]);
   }
  }
 }
}
//菜单打印
void Menu(){
 printf("\n————————菜单————————\n");
 printf("\n1.创建图结构;\n");
 printf("\n2.深度遍历(DFS);\n");
 printf("\n3.广度遍历(BFS);\n");
 printf("\n0.退出;\n");
 printf("\n——————————————————\n");
 printf("[请输入你的选择:]\n>>>");
}
//主函数
int main(){
 int i,user;
 char v;
 AMGraph G;
 while(1){
  Menu();
  scanf("%d",&user);
  switch(user){
  case 1:{
   CreateUDN(G);
   break;
  }
  case 2:{
   //初始化辅助数组
   for(i=0;i<G.vexnum;i++)
    visited[i] = 0;
   printf("[请输入遍历开始的顶点:]\n>>>");
   getchar();
   scanf("%c",&v);
   DFS_AM(G,v);
   break;
  }
  case 3:{
   //初始化辅助数组
   for(i=0;i<G.vexnum;i++)
    visited[i] = 0;
   printf("[请输入遍历开始的顶点:]\n>>>");
   getchar();
   scanf("%c",&v);
   BFS_AM(G,v);
   break;
  }
  case 0:{
   exit(0);
   break;
  }
  }
 }
 return 0;
}

五、 实验结果

六、总结与思考

  • 无向图的邻接矩阵是对称的,有向图邻接矩阵可能不对称。
  • 深度优先搜索类似于栈结构的出栈于入栈过程,模拟递归,其实递归也是通过堆栈的形式实现的。
  • 广度遍历是非递归过程,借助队列来实现。
  • 辅助数组需要在全局使用,在主函数外定义。
  • DFS与BFS空间复杂度都是O(n),邻接矩阵时间复杂度都是O(n2),邻接表时间复杂度为O(n+e)。

邻接矩阵示意图:

以上就是C语言数据结构图的创建与遍历实验示例的详细内容,更多关于C语言数据结构图的创建遍历的资料请关注脚本之家其它相关文章!

相关文章

  • C语言强制类型转换规则实例详解

    C语言强制类型转换规则实例详解

    强制类型转换是把变量从一种类型转换为另一种数据类型,下面这篇文章主要给大家介绍了关于C语言强制类型转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • C语言中sscanf()函数的字符串格式化用法

    C语言中sscanf()函数的字符串格式化用法

    这篇文章介绍的是C语言中sscanf()函数,本文介绍了sscanf()函数的含义与用法,对大家日常使用C语言的sscanf()函数很有帮助,有需要的可以参考借鉴。
    2016-08-08
  • C++中auto类型说明符详解(附易错实例)

    C++中auto类型说明符详解(附易错实例)

    这篇文章主要给大家介绍了关于C++中auto类型说明符的相关资料,文中还附易错实例,在C++11中引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型,需要的朋友可以参考下
    2023-07-07
  • C++算法之在无序数组中选择第k小个数的实现方法

    C++算法之在无序数组中选择第k小个数的实现方法

    这篇文章主要介绍了C++算法之在无序数组中选择第k小个数的实现方法,涉及C++数组的遍历、判断、运算等相关操作技巧,需要的朋友可以参考下
    2017-03-03
  • C语言的动态内存管理你了解吗

    C语言的动态内存管理你了解吗

    这篇文章主要为大家详细介绍了C语言的动态内存管理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • C++浅析内联函数的使用

    C++浅析内联函数的使用

    为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数
    2022-05-05
  • C++的运算符你真的了解吗

    C++的运算符你真的了解吗

    这篇文章主要为大家详细介绍了C++的运算符,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++获取特定进程CPU使用率的实现代码

    C++获取特定进程CPU使用率的实现代码

    写一个小程序在后台记录每个进程的CPU使用情况,揪出锁屏后占用CPU的进程,于是自己写了一个C++类CPUusage,方便地监视不同进程的CPU占用情况。本人编程还只是个新手,如有问题请多多指教
    2019-04-04
  • C语言 数据结构之数组模拟实现顺序表流程详解

    C语言 数据结构之数组模拟实现顺序表流程详解

    顺序表,全名顺序存储结构,是线性表的一种,线性表用于存储逻辑关系为“一对一”的数据,顺序表自然也不例外,不仅如此,顺序表对数据的物理存储结构也有要求,跟随下文来具体了解吧
    2021-11-11
  • C语言数据类型与sizeof关键字

    C语言数据类型与sizeof关键字

    这篇文章主要介绍了C语言数据类型与sizeof关键字,C语言的数据类型包括基本类型、构造类型、指针类型以及空类型,下文更多相关内容需要的小伙伴可以参考一下
    2022-04-04

最新评论