【实验内容】
设无向图G有n个点e条边,写意算法建立G的邻接多表,并按照深度优先搜索输出顶点,要求该算法时间复杂性为O(n+e),且除邻接多表本身所占空间之外只用O(1)辅助空间。
【参考方法】
邻接表定义:
#include<stdio.h>
#include<stdlib.h>
#define max 30
typedef struct edgenode{
int adjvex;
char info;
struct edgenode *next;
};
typedef struct vexnode{
char data;
struct edgenode *link;
}adjlist[max];
题目分析:
1、此题主要需要的是对邻接表的创建和遍历的理解,在要求上事实上比较简单。(笔者一共花了3小时不到就做完了)但是题目给的“邻接表定义”说实话有点乱,笔者在代码中还是按照自己的想法写了。
2、之后笔者又花了半个小时的时间对代码进行的进一步修改:由于是无向图所以一条边要增加两个结点,另外也是修改了一个小bug。并且也使用了更复杂的数据来测试。
3、做邻接表的遍历,做题者对递归需要有一定的理解,否则会觉得很难。
4、由于要改变指针所指向的值,所以用到了双重指针。
5、由于此题还是要用到递归,使用C++比较麻烦,所以选用C来写。(在申请空间的时候还是用到了new)
6、笔者由于要调试,所以用的编译器是visual c++,使用codeblocks的读者在运行代码的时候需要在for中给i定义。
效果:
#include<stdio.h>
#include<iostream>
#define Max 30
using namespace std;
typedef struct edgenode{
int adjvex; //指向的顶点的下标
struct edgenode *next;//指向下一条边的指针
}edgenode;
typedef struct vexnode{
char data; //顶点的权值
struct edgenode *link; //指向一条与该顶点相连的边的指针
}vexnode;
typedef struct Graph{
vexnode xlist[Max];
int vexnum,edgenum;
}Graph;
void CreateGraph(Graph &g)
{
printf("请输入顶点的个数:");
scanf("%d",&g.vexnum);
for(int i=0;i<g.vexnum;i++)//把与顶点相连的边设为空
g.xlist[i].link=NULL;
printf("请输入边的个数:");
scanf("%d",&g.edgenum);
printf("请输入各个顶点的值:(顶点之间用空格分离)\n");
getchar();
for(i=0;i<g.vexnum;i++)
{
g.xlist[i].data=getchar();
getchar();
}
printf("请输入各个边的值:(形式如a-b,各边之间用空格分离)\n");
for(i=0;i<g.edgenum;i++)
{
char tail,head;
int tail_num=-1,head_num=-1;
tail=getchar();
getchar();
head=getchar();
getchar();
//查找边的两个结点的下标
for(int i=0;i<g.vexnum;i++)
{
if(g.xlist[i].data==tail)
tail_num=i;
if(g.xlist[i].data==head)
head_num=i;
//如果两者都已经找到那么就退出循环
if(tail_num!=-1&&head_num!=-1)
break;
}
//由于是无向图,所以要添加两个结点
int t=2;
while(t--)
{
//创建新的边结点并且赋值
edgenode *s;
s=new edgenode;
s->adjvex=head_num;
s->next=NULL;
//由于要改变指针所指向的值,所以要用双重指针
// 一直到next_node的值为空才给他赋值
//避免新的边覆盖之前的边
edgenode **next_node=&g.xlist[tail_num].link;
while(*next_node)
{
next_node=&((*next_node)->next);
}
*next_node=s;
//交换顶点位置,进入下一个循环
int swap;
swap=tail_num;
tail_num=head_num;
head_num=swap;
}
}
}
//定义一个bool数组来查看顶点是否被遍历过
static bool visited[Max];
//由于在PrintGraph中会用到递归,所以要先声明
void DFS(Graph g,int i);
void PrintGraph(Graph g)
{
for(int i=0;i<g.vexnum;i++)
visited[i]=false;
printf("深度优先搜索输出的顶点的值分别为:\n");
for(i=0; i<g.vexnum; i++)
if(!visited[i])
DFS(g,i);
printf("\n");
}
void DFS(Graph g,int i)
{
visited[i]=true;//标记已经遍历过
printf("%c ",g.xlist[i].data);
//nextNode来代表下一个相关边
edgenode *nextNode=g.xlist[i].link;
//如果下一个相关边不为空且没有遍历过
while(nextNode)
{
if(!visited[nextNode->adjvex])
DFS(g,nextNode->adjvex);
nextNode=nextNode->next;
}
}
int main()
{
Graph g;
CreateGraph(g);
printf("\n");
PrintGraph(g);
printf("\n");
return 0;
}