数据结构实验四五六
- 格式:doc
- 大小:122.00 KB
- 文档页数:36
数据结构实验实验四、图遍历的演示。
【实验学时】5学时【实验目的】(1)掌握图的基本存储方法。
(2)熟练掌握图的两种搜索路径的遍历方法。
【问题描述】很多涉及图上操作的算法都是以图的遍历操作为基础的。
试写一个程序,演示连通的无向图上,遍历全部结点的操作。
【基本要求】以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。
【测试数据】教科书图7.33。
暂时忽略里程,起点为北京。
【实现提示】设图的结点不超过30个,每个结点用一个编号表示(如果一个图有n个结点,则它们的编号分别为1,2,…,n)。
通过输入图的全部边输入一个图,每个边为一个数对,可以对边的输入顺序作出某种限制。
注意,生成树的边是有向边,端点顺序不能颠倒。
【选作内容】(1)借助于栈类型(自己定义和实现),用非递归算法实现深度优先遍历。
(2)以邻接表为存储结构,建立深度优先生成树和广度优先生成树,再按凹入表或树形打印生成树。
(3)正如习题7。
8提示中分析的那样,图的路径遍历要比结点遍历具有更为广泛的应用。
再写一个路径遍历算法,求出从北京到广州中途不过郑州的所有简单路径及其里程。
【源程序】#include<iostream.h>#include <stdio.h>#include <stdlib.h>#define MAX_VERTEX_NUM 20#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define TRUE 1#define OK 1#define FALSE 0#define ERROR 0#define OVERFLOW -2typedef enum{DG,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网}bool visited[MAX_VERTEX_NUM];typedef struct ArcNode{int adjvex;//该弧所指向的顶点在数组中的下标struct ArcNode *nextarc;int *info;//该弧相关信息的指针}ArcNode;typedef struct VNode{int data;//顶点信息ArcNode *firstarc;//指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;//图的当前顶点数和弧数int kind;//图的种类标志}ALGraph;typedef structint *base;int *top;int stacksize;}SqStack;typedef struct QNode{int data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;int LocateVex(ALGraph G,int v) {//返回数组下标值int i;for(i=0;i<MAX_VERTEX_NUM;++i)if(G.vertices[i].data==v) return i;return -1;}void CreateDN(ALGraph &G){//采用邻接表存储表示,构造有向图G(G.kind=DN) int i,j,k;ArcNode *p;int v1,v2;G.kind=DN;printf(" 输入顶点数:");scanf("%d",&G.vexnum);printf(" 输入弧数:");scanf("%d",&G.arcnum);printf(" 输入顶点:\n");for(i=0;i<G.vexnum;++i){//构造表头向量scanf("%d",&G.vertices[i].data);G.vertices[i].firstarc=NULL;//初始化指针}for(k=0;k<G.arcnum;++k){printf("第%d条弧: ",k+1);scanf("%d",&v1);scanf("%d",&v2);//输入一条弧的始点和终点i=LocateVex(G,v1);j=LocateVex(G,v2);//确定v1和v2在G中位置p=(ArcNode*)malloc(sizeof(ArcNode));//假定有足够空间p->adjvex=j;p->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p;scanf("%d",&p->info);}//for}int Push(SqStack &S,int e){//插入元素e为新的栈顶元素if(S.top-S.base>=S.stacksize){//栈满,追加存储空间S.base=(int*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(int));if(!S.base)exit(OVERFLOW); //存储分配失败S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}int InitStack(SqStack &S) //栈的初始化{S.base=(int*)malloc(STACK_INIT_SIZE*sizeof(int));if(!S.base)exit(OVERFLOW); //存储分配失败S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}int Pop(SqStack &S,int &e) //删除栈顶元素{//若栈不空,则删除S的栈顶元素,用e返回其值if(S.top==S.base)return ERROR;e=*--S.top;return OK;}int GetTop(SqStack S,int &e) //取栈顶元素{//若栈不空,则用e返回S的栈顶元素if(S.top==S.base)return ERROR;e=*(S.top-1);return OK;}int StackEmpty(SqStack S) //栈空{if(S.top==S.base)return TRUE;elsereturn FALSE;}int InitQueue(LinkQueue &Q) //队列初始化{Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(OVERFLOW);Q.front->next=NULL;return OK;}int EnQueue(LinkQueue &Q,int e) //插入{//插入元素e为Q的新的队尾元素QueuePtr p=(QueuePtr)malloc(sizeof(QNode)); if(!p)exit(OVERFLOW);p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;return OK;}int DeQueue(LinkQueue &Q,int &e){//若队列不空,则删除Q的队头元素,用e返回其值if(Q.front==Q.rear)return ERROR;QueuePtr p=Q.front->next;e=p->data;Q.front->next=p->next;if(Q.rear==p)Q.rear=Q.front;free(p);return OK;}int QueueEmpty(LinkQueue Q) //队列空{if(Q.front==Q.rear)return TRUE;elsereturn FALSE;}int FirstAdjVex(ALGraph G,int u){if(!G.vertices[u].firstarc)return -1;return LocateVex(G,G.vertices[u].firstarc->adjvex); }int NextAdjVex(ALGraph G,int u,int w){ArcNode *p=G.vertices[u].firstarc;while(p&&LocateVex(G,p->adjvex)!=w)p=p->nextarc;if(!p)return FirstAdjVex(G,u);p=p->nextarc;if(!p)return -1;return LocateVex(G,p->adjvex);}void Visit(ALGraph G,int v){printf("%2d",G.vertices[v].data);}void DFSTraverse(ALGraph G){//按深度优先非递归遍历图G,使用辅助栈S和访问标志数组visited int v,w;SqStack S;for(v=0;v<G.vexnum;v++)visited[v]=FALSE;InitStack(S);for(v=0;v<G.vexnum;++v)if(!visited[v]){//v尚未被访问visited[v]=TRUE;Visit(G,v);Push(S,v);//v进栈while(!StackEmpty(S)){for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){if(!visited[w]){Visit(G,w);visited[w]=TRUE;Push(S,w);GetTop(S,v);}//if}//forPop(S,v);GetTop(S,v);}//while}//ifprintf("\n");}void BFSTraverse(ALGraph G){//按广度优先非递归遍历图G,使用辅助队列Q和访问标志数组visited int v,u,w;LinkQueue Q;for(v=0;v<G.vexnum;++v)visited[v]=FALSE;InitQueue(Q);for(v=0;v<G.vexnum;++v)if(!visited[v]){//v尚未被访问visited[v]=TRUE;Visit(G,v);EnQueue(Q,v);//v入队列while(!QueueEmpty(Q)){DeQueue(Q,u);//队头元素出队并置为ufor(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(!visited[w]){//w为u的尚未访问的邻接顶点visited[w]=TRUE;Visit(G,w);EnQueue(Q,w);}//if}//while}//ifprintf("\n");}void PrintDN(ALGraph G) //图的显示{int i;ArcNode *p;printf("顶点:\n");for(i=0;i<G.vexnum;++i)printf("%2d",G.vertices[i].data);printf("\n弧:\n");for(i=0;i<G.vexnum;++i){p=G.vertices[i].firstarc;if(p){while(p){printf("%d→%d(%d)\t",i,p->adjvex,p->info);p=p->nextarc;}printf("\n");}//if}//for}void main(){ALGraph G;printf("************题目:图的遍历***************\n\n"); CreateDN(G);PrintDN(G);printf(" 深度优先遍历:");DFSTraverse(G);printf("\n 广度优先遍历:");BFSTraverse(G);}【运行结果】实验五查找算法实现【实验学时】5学时【实验目的】熟练掌握顺序查找、折半查找及二叉排序树、平衡二叉树上的查找、插入和删除的方法,比较它们的平均查找长度。