计算机科学与技术专业课程设计任务书说明:本表由指导教师填写,由教研室主任审核后下达给选题学生,装订在设计(论文)首页课程设计课程设计名称:数据结构专业班级:学生姓名:学号:指导教师:课程设计时间:一、需求分析对任意给定的图(顶点数和边数自定义),建立它的邻接表输出,然后利用栈的五种基本运算(清空堆栈,压栈,弹出,取栈顶元素,判空栈)实现图的深度搜索遍历和广度优先搜素遍历算法二、概要设计邻接表是图的一种链式存储结构为,类似于树的孩子链表表法。
在邻接表中,对图中每个顶点建立一个单链表,n个顶点,就要建n个链表。
对于无向图,第i 个单链表中的结点表示依赖于顶点v i的边。
对于有向图是以顶点v i为尾的弧,这个单链表称为顶点v i的单链表(即V i的邻接表)。
单链表中每一个结点称为表结点,应包括两个域:邻接点域,用以存放与v i相邻接的顶点序号;链域用以指向民v i邻接的下一个结点。
另外,每一个单链表设一个表头结点。
每一个表头结点有两个域,一个用来存放顶点vi的信息;另一个域用来指向v i的邻接表中的第一个结点。
为了便于管理和随机访问任一顶点的单链表,将所有单链表的头结点组织成一个一维数组。
顶点链头顶点地址链针邻接表的表头和表结点形式typedef struct node{int adjvex;//弧指向顶点的位置struct node *next;//指向下一条弧的指针}edgenode;//表结点typedef struct {//头结点char vertex;//顶点信息edgenode *link;//指向第一条依附该顶点的弧的指针}vexnode,AdjList[maxvertexnum];建立邻接表的方法是:首先将邻接表表头数组初始化,第i个表头的vertex初始化为i,;link初始化为NULL。
然后读入顶点对<i.j>,产生一个表结点,将j 放入到该结点的adjvex域,将该结点链到邻接表的表头的T第i个表头的link 域上。
深度优先遍历算法1.现将所有的顶点标记为未访问2.输出起始顶点,同时置起始顶点已访问的标记3.将起始顶点进栈4.当栈不为空时重复执行以下步骤a取当前栈顶顶点b若栈顶顶点存在未被访问的邻接结点,则选择一个顶点进行一下步骤:输出该顶点置该顶点已访问标记将该顶点进栈c否测当前顶点退栈存储结构typedef struct{//栈int *data;//栈底指针int *top;//栈顶指针}seqstack;广度优先遍历算法1.现将所有的顶点标记为未访问2.访问选定的起始顶点3.置起始顶点已访问标记,并将该顶点入队4.当队列不空时a取对头顶点b依次访问与顶点相邻的未被访问的顶点访问该顶点置该顶点为已被访问的标记,并将它入队c当前对头元素顶点出队d重复进行直到对空时结束三、运行环境(软、硬件环境)Windows98操作系统.VisualC++6.0软件环境下编译运行四、开发工具和编程语言开发工具和编程语言:(数据结构)C语言数据结构(c语言)五、详细设计#include<stdio.h>#include<stdlib.h>#include <malloc.h>#define False 0#define True 1#define Null 0#define maxsize 20//队列的最大空间#define maxvertexnum 20//最大顶点数typedef struct node{int adjvex;//弧指向顶点的位置struct node *next;//指向下一条弧的指针}edgenode;//表结点typedef struct {//头结点char vertex;//顶点信息edgenode *link;//指向第一条依附该顶点的弧的指针}vexnode,AdjList[maxvertexnum];typedef struct{//图AdjList adjlist;int n,e;//n顶点数,e边数}Graph;typedef struct{//栈int *data;//栈底指针int *top;//栈顶指针}seqstack;//全局变量vexnode g[maxvertexnum];//先定义后使用vexnode,邻接表g为全程变量int visited[maxvertexnum]; //定义visit为全程向量void CreatAdjList(Graph &G){int i,j,k;//i,j为邻接点序号edgenode *s;char c;printf("请输入定点数和边数:\n");scanf("%d,%d",&G.n,&G.e);c=getchar();printf("请输入顶点信息(顶点号):\n");for(i=1;i<=G.n;i++){//建立有n个顶点的顶点表printf("第%d个顶点为",i);scanf("%c",&G.adjlist[i].vertex);c=getchar();G.adjlist[i].link=NULL;}printf("请输入边的信息():\n");for(k=1;k<=G.e;k++){//建立边表printf("请输入请输入第%d条边起始顶点编号:\n",k);scanf("%d",&i);printf("请输入请输入第%d条边终顶点编号:\n",k);scanf("%d",&j);s=(edgenode*)malloc(sizeof(edgenode));//分配顶点空间s->adjvex=j;s->next=G.adjlist[i].link;G.adjlist[i].link=s;}}void DisplayAdjList(Graph G){int i;edgenode *q;for(i=1;i<=G.n;++i){q=G.adjlist[i].link;printf("%d",i);while(q!=NULL){printf("->%d",q->adjvex);q=q->next;}printf("\n");}}void DFSAL(Graph G){edgenode *p;seqstack s;int i=1,t;for(i=1;i<=G.n;i++)visited[i]=0;printf("这是深度优先遍历,遍历顺序为:\n");//输出起始顶点s.data=(int*)malloc(maxsize*sizeof(seqstack));s.top=s.data;//初始化栈for(i=1;i<=G.n;i++)//考虑到图可能不连通{p=G.adjlist[i].link;t=i;if(p==NULL)//p==NULL时,即该结点没有邻结点{if(!visited[t]){printf("%c",G.adjlist[t].vertex);//如果此时该结点没有被访问过,则访问visited[t]=True;}continue;//即该结点没有邻结点,本次循环结束}do{if(p==NULL)//即到了图的最底层{s.top--;//没有下个邻接点,则退回前一个顶点p=G.adjlist[*s.top].link;if(p!=NULL){t=p->adjvex;}}else if(!visited[t])//该结点中p!=NULL且其没有被访问过{printf("%c",G.adjlist[t].vertex);//输出该顶点visited[t]=True;//置为已访问if(G.adjlist[t].link==NULL)continue;*s.top=t;s.top++;//进栈p=G.adjlist[t].link;//p指针指到以G.adjlist[t].vertex为起点的第一条边,如果//p==NULLif(p==NULL)//如果该结点没有邻接点则输出之{if(!visited[t])printf("%c",G.adjlist[t].vertex);}else t=p->adjvex;//如果该结点有邻接点,则把其邻接点的顶点号赋值给t}else//如果该结点被访问过,且有邻结点,p指向以当前结点的邻接点为起点的边//也可能P=NULL{p=p->next;if(p!=NULL)t=p->adjvex;//如果该邻接点有邻接点,则记下其邻接点的位置}}while(s.top!=s.data);}}void BFSAL(Graph G){int v,Q[maxsize];edgenode * w;printf("这是广度优先遍历,遍历顺序为:\n");int front=0,rear=0;//辅助队列置空for(v=1;v<=G.n;v++)visited[v]=0;for(v=1;v<=G.n;v++)if(!visited[v]){visited[v]=1;printf("%c",G.adjlist[v].vertex);Q[rear]=v;rear++; //入队while (front!=rear){ //队不空front++; //出队w=G.adjlist[v].link;while(w){if(!visited[w->adjvex]){visited[w->adjvex]=1;// 访问w;printf("%c",G.adjlist[w->adjvex].vertex);Q[rear]=w->adjvex;rear++;}w=w->next;}}}}void main(){Graph G;int choice;char ch;printf("------创建邻接表存储的图");CreatAdjList(G);printf("已创建一个图了邻接表\n");DisplayAdjList(G)while(ch!='n'){printf("\n请选择操作:");printf("\n1------深度优先遍历:");printf("\n2------广度优先遍历");printf("\n3-----退出\n");scanf("%d",&choice);switch(choice){case 1:DFSAL(G);break;case 2:BFSAL(G);break;case 3:ch='n';break;default:ch='n';}}}}六、调试分析在图的创建过程中就遇到了问题,应为少了接受字符的getchar()函数,使得再输入顶点信息(字符型)后无法再执行CreatAdjlist()中剩下的语句,导致创建失败!再经同学提醒后成功创建了图。