数据结构图及其应用实验报告+代码

合集下载

数据结构实验报告(C语言)(强力推荐)

数据结构实验报告(C语言)(强力推荐)

数据结构实验实验内容和目的:掌握几种基本的数据结构:集合、线性结构、树形结构等在求解实际问题中的应用,以及培养书写规范文档的技巧。

学习基本的查找和排序技术。

让我们在实际上机中具有编制相当规模的程序的能力。

养成一种良好的程序设计风格。

实验教材:数据结构题集(C语言版)清华大学出版社2007年实验项目:实验一、栈和循环队列㈠、实验内容:①栈掌握栈的特点(先进后出FILO)及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构,以便在实际问题背景下灵活应用。

本程序采用的是链栈结构,具有初始化一个栈、PUSH、POP、显示所有栈里的元素四个功能。

②循环队列掌握队列的特点(先进先出FIFO)及基本操作,如入队、出队等,学会循环队列的实现,以便在实际问题背景下灵活运用。

本程序具有初始化一个队列、入队、出队、显示队列的所有元素、队列长度五个功能。

㈡、实验代码①栈程序代码:#include <stdio.h>#include <malloc.h>#define Stack_Size 6#define ERROR 0#define OK 1typedef int SElemType;typedef struct SNode{SElemType data;struct SNode *next;}SNode,*LinkStack;int CreatTwo(LinkStack &head,int n){int i;SNode *p;head=(LinkStack)malloc(sizeof(SNode));head->next=NULL;printf("请输入数据(数字):\n");for(i=n;i>0;--i){p=(SNode *)malloc(sizeof(SNode));scanf("%d",&p->data);p->next=head->next;head->next=p;}return 1;}int menu_select(){int sn;for(;;){scanf("%d",&sn);if(sn<1||sn>6)printf("\n\t输入错误,请重新输入\n");elsebreak;}return sn;}int Push(LinkStack &top,SElemType e){SNode *q;q=(LinkStack)malloc(sizeof(SNode));if(!q){printf("溢出!\n");return(ERROR);}q->data=e;q->next=top->next;top->next=q;return(OK);}int Pop(LinkStack &top,SElemType &e){SNode *q;if(!top->next){printf("error!\n");return(ERROR);}e=top->next->data;q=top->next;top->next=q->next;free(q);return(OK);}void main(){ int e;LinkStack top;printf("1.初始化一个栈;\n2.PUSH;\n3.POP;\n4.显示所有栈里的元素;\n5.结束;\n");while(1){switch(menu_select()){case 1:if(CreatTwo(top,Stack_Size))printf("Success!\n");break; case 2:printf("Push:\n");scanf("%d",&e);if(Push(top,e))printf("Success!\n");break;case 3:if(Pop(top,e))printf("Success!\n");printf("%d\n",e);break;case 4:LinkStack p;printf("所有栈里的元素:\n");p=top;while(p->next){p=p->next;printf("%7d",p->data);}printf("\n");break;case 5:return;}}}运行结果:②循环队列程序代码:#include<stdlib.h>#include<stdio.h>#define OVERFLOW -1#define OK 1#define ERROR 0#define MAXSIZE 100typedef struct{int *elem;//队列存储空间int front;int rear;}SqQueue;//判断选择是否正确int menu_select(){int sn;for(;;){scanf("%d",&sn);if(sn<1||sn>6)printf("\n\t输入错误,请重新输入\n");elsebreak;}return sn;}//参数(传出)SqQueue &Q,循环队列(空)int InitQueue(SqQueue &Q){Q.elem=(int *)malloc(MAXSIZE*sizeof(int));if(!Q.elem)exit(OVERFLOW);Q.front=Q.rear=-1;for(int i=0;i<MAXSIZE;i++)Q.elem[i]=-1;return OK;}//返回Q的元素个数int QueueLength(SqQueue Q){return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;}//显示队列的元素void Display(SqQueue Q){for(int i=0;i<=QueueLength(Q);i++)if(Q.elem[i]!=-1)printf("%d ",Q.elem[i]);printf("\n");}//入队int EnQueue(SqQueue &Q,int e){Q.rear=(Q.rear+1)%MAXSIZE;if(Q.rear==Q.front)return ERROR;Q.elem[Q.rear]=e;return OK;}//出队int DeQueue(SqQueue &Q,int &e){if(Q.front==Q.rear)return ERROR;e=Q.elem[Q.front+1];Q.elem[Q.front+1]=-1;Q.front=(Q.front+1)%MAXSIZE;return OK;}void main(){SqQueue Q;InitQueue(Q);int elem,e;printf("请输入队列元素(以0结束):\n");scanf("%d",&elem);while(elem!=0){EnQueue(Q,elem);scanf("%d",&elem);}printf("队列为:\n");Display(Q);printf("1.初始化一个队列;\n2.入队;\n3.出队;\n4.显示队列的所有元素;\n5.队列长度:\n6.结束;\n");while(1){switch(menu_select()){case 1:printf("请输入队列元素(以0结束):\n");scanf("%d",&elem);while(elem!=0){EnQueue(Q,elem);scanf("%d",&elem);}printf("队列为:\n");Display(Q);fflush(stdin);break;case 2:scanf("%d",&elem);EnQueue(Q,elem);printf("队列为:\n");Display(Q);fflush(stdin);break;case 3:DeQueue(Q,elem);printf("队列为:\n");Display(Q);break;case 4:printf("\n队列的所有元素:\n");Display(Q);break;case 5:printf("%d\n",QueueLength(Q));break;case 6:return;}}}运行结果:实验二、数组㈠、实验内容:数组一般不做插入或删除操作,也就是说,一旦建立了数组,则结构中的数据元素个数和元素之间的关系就不再发生变动。

数据结构实验代码2

数据结构实验代码2

数据结构实验代码2第一点:数据结构实验代码2的背景与意义数据结构是计算机科学中至关重要的一个领域,它研究如何有效地存储、组织和管理数据,以及如何高效地执行相关操作。

在现代软件开发和计算机科学教育中,理解和掌握数据结构是不可或缺的。

数据结构实验代码2,作为一个具体的实践案例,旨在帮助学生深化对数据结构理论知识的理解,通过亲自动手编写和调试代码,增强对数据结构在实际应用中的认识。

实验代码2通常涉及到复杂的数据结构,比如图(Graph)、树(Tree)的高级算法实现,比如深度优先搜索(DFS)、广度优先搜索(BFS)、最短路径算法(如Dijkstra或Bellman-Ford算法)、最小生成树算法(如Prim或Kruskal算法)等。

通过对这些算法的实验实现,学生不仅能够掌握算法的工作原理,还能够理解其在解决实际问题时的效率和适用场景。

此外,数据结构实验代码2也是对学生编程能力和问题解决能力的一种锻炼。

在编写代码的过程中,学生需要考虑到算法的效率、空间复杂度,以及代码的可读性和可维护性。

这对于学生将来从事软件开发工作,具有重要的现实意义。

在当前的数字经济时代,数据结构的掌握程度直接关系到软件质量的高低和开发效率的快慢,因此,数据结构实验代码2在计算机科学与技术教育中占有举足轻重的地位。

第二点:数据结构实验代码2的关键技术与实现步骤数据结构实验代码2在技术实现上,涉及多个关键的步骤和考虑因素。

首先,学生需要选择合适的编程语言和开发环境,这对于代码的编写和调试都是非常重要的。

常见的编程语言如C/C++、Java、Python等,都具备实现复杂数据结构和算法的性能和灵活性。

接下来,是数据结构的具体实现。

这要求学生不仅要熟悉类和对象的概念,还需要能够设计出既符合数据结构特性,又能够有效实现算法逻辑的类和对象。

例如,在实现图的数据结构时,学生需要定义图的节点(Vertex)和边(Edge),并且提供添加节点、添加边、查找节点等基础操作。

数据结构上机实验源代码

数据结构上机实验源代码

数据结构上机实验源代码栈的应用十进制数转换为八进制数,逆序输出所输入的数实验代码://stack.h,头文件class stack{public:stack();bool empty()const;bool full()const;error_code gettop(elementtype &x)const;error_code push(const elementtype x);error_code pop();private:int count;elementtype data[maxlen];};stack::stack(){count=0;}bool stack::empty()const{return count==0;}bool stack::full()const{return count==maxlen;}error_code stack::gettop(elementtype &x)const{if(empty())return underflow;else{x=data[count-1];return success;}}error_code stack::push(const elementtype x){if(full())return overflow;data[count]=x;count++;return success;}error_code stack::pop(){if(empty())return underflow;count--;return success;}//主程序#include<iostream.h>enum error_code{overflow,underflow,success};typedef int elementtype;const int maxlen=20;#include"stack.h"void read_write() //逆序输出所输入的数{stack s;int i;int n,x;cout<<"please input num int n:";cin>>n;for(i=1;i<=n;i++){cout<<"please input a num:";cin>>x;s.push(x);}while(!s.empty()){s.gettop(x);cout<<x<<" ";s.pop();}cout<<endl;}void Dec_to_Ocx(int n) //十进制转换为八进制{stack s1;int mod,x;while(n!=0){mod=n%8;s1.push(mod);n=n/8;}cout<<"the ocx of the dec is:";while(!s1.empty()){s1.gettop(x);cout<<x;s1.pop();}cout<<endl;}void main(){int n;// read_write();cout<<"please input a dec:";cin>>n;Dec_to_Ocx(n);}队列的应用打印n行杨辉三角实验代码://queue.hclass queue{public:queue(){count=0;front=rear=0;}bool empty(){return count==0;}bool full(){return count==maxlen-1;}error_code get_front(elementtype &x){if(empty())return underflow;x=data[(front+1)%maxlen];return success;}error_code append(const elementtype x){if(full())return overflow;rear=(rear+1)%maxlen;data[rear]=x;count++;return success;}error_code serve(){if(empty())return underflow;front=(front+1)%maxlen;count--;return success;}private:int count;int front;int rear;int data[maxlen];};//主程序#include<iostream.h>enum error_code{overflow,underflow,success};typedef int elementtype;const int maxlen=20;#include"queue.h"void out_number(int n) //打印前n行的杨辉三角{int s1,s2;int i;int j;int k;queue q;for(i=1;i<=(n-1)*2;i++)cout<<" ";cout<<"1 "<<endl;q.append(1);for(i=2;i<=n;i++){s1=0;for(k=1;k<=(n-i)*2;k++)cout<<" ";for(j=1;j<=i-1;j++){q.get_front(s2);q.serve();cout<<s1+s2<<" ";q.append(s1+s2);s1=s2;}cout<<"1 "<<endl;q.append(1);}}void main(){int n;cout<<"please input n:";cin>>n;out_number(n);}单链表实验实验目的:实验目的(1)理解线性表的链式存储结构。

数据结构实验报告代码

数据结构实验报告代码

《数据结构》实验报告实验序号:5 实验项目名称:链式栈五、分析与讨论对上机实践结果进行分析,上机的心得体会。

六、教师评语成绩签名:日期:附源程序清单:实验要求编程实现如下功能:(1)按照输入的栈中元素个数n和各元素值成立一个顺序栈,并输出栈中各元素值。

(2)将数据元素e入栈,并输出入栈后的顺序栈中各元素值。

(3)将顺序栈中的栈顶元素出栈,并输出出栈元素的值和出栈后顺序栈中各元素值。

2. 实验相关原理:栈是一种插入和删除操作都限制在表的一端进行的特殊线性表,它的操作具有“先进后出”的特性。

采用顺序存储结构的栈称为顺序栈。

栈的存储结构描述如下:#define MAXSIZE 100; /*顺序栈的最大长度*/typedef struct{ Selemtype base[MAXSIZE]; /*存储栈中数据元素的数组*/int top; /*top为栈顶指针,它指示栈顶元素的存储空间的下一个存储单元*/}Sqstack;【核心算法提示】1.顺序栈入栈操作的大体步骤:第一判断顺序栈是不是为满,若是满,则函数返回ERROR,不然将待入栈的数据元素寄存在top所指示的存储单元中,再使top后移一个存储单元位置,即将top值加1,最后函数返回OK。

2.顺序栈出栈操作的大体步骤:第一判断顺序栈是不是为空,若是空,则函数返回ERROR,不然将栈顶指针前移一个存储单元位置,即将top值减1,再将top所指示的栈顶元素用e返回其值,并使函数返回OK。

【核心算法描述】status Push(Sqstack &S,Selemtype e)/*将数据元素e压入到顺序栈S中,使其成为新的栈项元素*/{ if >=MAXSIZE) /*若是栈满,则函数返回ERROR*/return ERROR;[++]=e;/*将新元素e寄存在top所指示的存储单元中,并使top值加1*/return OK;}status Pop(Sqstack &S,Selemtype &e)/*将顺序栈S中的栈顶元素从栈中删除,并用e返回其值*/{ if ==0) /*若是栈空,则函数返回ERROR*/Return ERROR;e=[];/*将top值减1,并用e保留top所指示的栈顶元素值*/return OK;}3.源程序代码参考#define MAXSIZE 100typedef struct{ int base[MAXSIZE];int top; /*top指示存储栈顶元素的下一存储单元*/}Sqstack; /*顺序栈的类型概念*/Sqstack Push(Sqstack S,int e) /*顺序栈的入栈操作函数*/{ if >=MAXSIZE)printf("Stack is Overflow\n");else[++]=e;return S;}Sqstack Pop(Sqstack S,int *e) /*顺序栈的出栈操作函数*/{ if ==0)printf("Stack is Empty\n");else*e=[];return S;}void Stack_display(Sqstack S) /*顺序栈的输出函数*/{ int i;for(i=0; i<;i++) /*依次输出栈中各元素的值,栈顶元素在表的尾部*/printf("%4d", [i]);printf("\n");}main(){ Sqstack S;int i,j,n,x,e;printf("please input the length:");/*请求输入顺序栈中元素个数*/scanf("%d",&n);printf("please input the Value:\n ");/*请求输入顺序栈中各个元素值*/for(i=0;i<n;i++)scanf("%d",&[i]);=n;printf("the stack is:\n");Stack_display(S);printf("please input the insert node:");/*请求输入需要入栈的新元素*/scanf("%d",&x);S=Push(S,x);printf("the stack after push is:\n");/*提示输出入栈后栈中各个元素值*/Stack_display(S); /*挪用顺序栈的输出函数*/S=Pop(S,&e);printf("the pop value is:%d\n",e); /*输出出栈元素的值*/printf("the stack after pop is:\n");/*提示输出出栈后栈中各个元素值*/Stack_display(S); /*挪用顺序栈的输出函数*/}(1)按照输入的栈中元素个数和各元素值成立一个链栈,并输出链栈中各元素值, 观察输入的内容与输出的内容是不是一致,特别注意栈顶元素的位置。

数据结构实验报告图的应用

数据结构实验报告图的应用

实验题目:图的应用一、实验目的和任务1 掌握图的邻接表和邻接矩阵存储;2 掌握图的拓扑排序算法;二、实验内容及原理1以下两项内容选做一项。

2 请按照书中介绍的拓扑排序算法,完成P303页第5题。

3 给定某一个图,完成其深度优先搜索遍历和广度优先搜索遍历,每种遍历都必须在邻接矩阵和邻接表中完成。

四、实验数据及程序代码#include <iostream.h>#include <stdlib.h>#include <strstrea.h>#include <string.h>#include <stdio.h>const int MaxVertexNum=10;typedef int WeightType;struct edgenode{int adjvex;WeightType weight;edgenode*next;};typedef edgenode *adjlist[MaxVertexNum];void InitAdjoin(adjlist GL)//初始化{for(int i=0;i<MaxVertexNum;i++)GL[i]=NULL;}void CreatAdjoin(adjlist GL,int n,char*s,int k1,int k2)//生成邻接表{istrstream sin(s);char c1,c2,c3;WeightType w;edgenode*p;sin>>c1;if(k2==0){do{sin>>c1>>i>>c2>>j>>c3;p=new edgenode;p->adjvex=j;p->weight=1;p->next=GL[i];GL[i]=p;if(k1==0){p=new edgenode;p->adjvex=i;p->weight=1;p->next=GL[j];GL[j]=p;}sin>>c1;}while(c1==',');}else{do{sin>>c1>>i>>c2>>j>>c3>>w;p=new edgenode;p->adjvex=j;p->weight=w;p->next=GL[i];GL[i]=p;if(k1==0){p=new edgenode;p->adjvex=i;p->weight=w;p->next=GL[j];GL[j]=p;}sin>>c1;}while(c1==',');}}void PrintAdjion(adjlist GL, int n,int k1, int k2) {edgenode*p;cout<<"V={";for(i=0; i<n-1; i++) cout<<i<<',';cout<<n-1<<'}'<<endl;cout<<"E={";for(i=0;i<n;i++){if(k2==0){p=GL[i];while(p){j=p->adjvex;if(k1==0){if(i<j) cout<<'('<<i<<','<<j<<')'<<',';}elsecout<<'<'<<i<<","<<j<<'>'<<',';p=p->next;}}else{p=GL[i];while(p){j=p->adjvex;if(k1==0){if(i<j) cout<<'('<<i<<','<<j<<')'<<p->weight<<',';}elsecout<<'<'<<i<<','<<j<<'>'<<p->weight<<',';p=p->next;}}}cout<<'}'<<endl;}void Toposort(adjlist GL , int n){int i,j,k,top,m=0;edgenode*p;int*d=new int[n];for(i=0;i<n;i++) d[i]=0;for(i=0;i<n;i++){p=GL[i];while(p!=NULL){j=p->adjvex;d[i]++;p=p->next;//cout<<j;}}top=-1;for(i=0;i<n;i++)if(d[i]==0){d[i]=top; top=i;}while(top!=-1){j=top;top=d[top];cout<<j<<' ';m++;p=GL[j];while(p!=NULL){k=p->adjvex;d[k]--;if(d[k]==0){d[k]=top;top=k;}p=p->next;}}cout<<endl;cout<<top<<endl;cout<<m<<endl;cout<<n<<endl;if(m<n) cout<<"The network has a cycle!"<<endl;delete []d;}void main(){int n,k1,k2;cout<<"输入待处理图的顶点数:";cin>>n;cout<<"输入图的有无向和有无权选择(0为无,非0为有):";cin>>k1>>k2;adjlist gl;InitAdjoin(gl);cout<<"输入图的边集:";FILE *p;p=fopen("d:\\1.txt","r+");char *a=new char[100];while (!feof(p)){fscanf(p,"%s ",a);cout<<a;}cout<<endl;//cin>>a;CreatAdjoin(gl,n,a,k1,k2);Toposort(gl,n);}五、实验数据分析及处理六、实验结论与感悟(或讨论)图的邻接矩阵,邻接表和边集数组表示各有利弊,具体运用时,要根据图的稠密和稀疏程度以及算法的要求进行选择。

数据结构实验报告图

数据结构实验报告图

数据结构实验报告图数据结构实验报告图问题描述:;四则运算表达式求值,将四则运算表达式用中缀表达式;一、需求分析:;1、本程序是利用二叉树后序遍历来实现表达式的转换;2、输入输出格式:;输入格式:在字符界面上输入一个中缀表达式,回车表;请输入表达式:;输入一个中缀表达式;输出格式:如果该中缀表达式正确,那么在字符界面上;式,其中后缀表达式中两相邻操作数之间利用空格隔开;果不正确,在字符界面上输出问题描述:四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。

一、需求分析:1、本程序是利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。

2、输入输出格式:输入格式:在字符界面上输入一个中缀表达式,回车表示结束。

请输入表达式:输入一个中缀表达式输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

逆波兰表达式为:3、测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+ 输出逆波兰表达式运算结果为:输出运算后的结果二、概要设计:抽象数据类型二叉树类BiTree算法的基本思想根据题目要求,利用栈计算,和二叉树存储,来计算表达式该算法的基本思想是:先利用栈进行计算,然后用二叉树进行存储,和实验三算法一样来计算逆波兰表达式的值程序的流程程序由三个模块组成:(1) 输入模块:输入一个运算式(2) 计算模块:利用栈进行表达式的计算,二叉树来存储。

(3 ) 输出模块:屏幕上显示出后缀表达式和运算结果。

三、详细设计物理数据类型程序含有两个类,其中栈不再赘述,另一个类为二叉树class BiTree包含私有成员struct BiTreeNode,根节点BiTreeNode *T;索引index; int number_of_point 优先级比较函数compare(char a,char b);生成树的函数void InorderCreate(BiTreeNode *&T,char str,int start,int end);判断数字函数bool IsNumber(char a);求值函数double Operate(BiTreeNode *T);还有显示后缀表达式的函数void display(BiTreeNode *T) ;而公有成员函数则是对私有函数的重载,为方便使用,因为函数中普遍使用了递归的算法。

《数据结构》实验指导书(源代码)

《数据结构》实验指导书(源代码)

实验一线性表的链式存储结构一、实验目的:1.掌握线性表的链式存储结构。

2.熟练地利用链式存储结构实现线性表的基本操作。

3.能熟练地掌握链式存储结构中算法的实现。

二、实验内容:1.用头插法或尾插法建立带头结点的单链表。

2.实现单链表上的插入、删除、查找、修改、计数、输出等基本操作。

三、实验要求:1. 根据实验内容编写程序,上机调试、得出正确的运行程序。

2. 写出实验报告(包括源程序和运行结果)。

四、实验学时:2学时五、实验步骤:1.进入编程环境,建立一新文件;2. 参考以下相关内容,编写程序,观察并分析输出结果。

①定义单链表的数据类型,然后将头插法和尾插法、插入、删除、查找、修改、计数、输出等基本操作都定义成子函数的形式,最后在主函数中调用它,并将每一种操作前后的结果输出,以查看每一种操作的效果。

②部分参考程序//单链表的建立(头插法),插入,删除,查找、修改、计数、输出#include<iostream.h>#define elemtype intstruct link{ elemtype data;//元素类型link *next; //指针类型,存放下一个元素地址};//头插法建立带头结点的单链表link *hcreat(){ link s,p;elemtype i;cout<<”输入多个结点数值(用空格分隔),为0时算法结束”;cin>>i;p=new link;p->next=NULL;while(i) //当输入的数据不为0时,循环建单链表{s=new link;s->data=i;s->next=p->next;p->next=s;cin>>i; }return p;}//输出单链表void print(1ink *head){1ink *p;p=head->next;while(p->next!=NULL){cout<<p->data<<”->”; //输出表中非最后一个元素p=p->next;}cout<<p->data; //输出表中最后一个元素cout<<endl;}∥在单链表head中查找值为x的结点Link *Locate(1ink *head,elemtype x){Link *p;p=head->next;while((p!=NULL)&&(p->data!=x))p=p->next;return p; }//在head为头指针的单链表中,删除值为x的结点void deletel(1ink *head,elemtype x){1ink *p, *q;q=head;p=head->next;while((p!=NULL)&&(p->data!=x)){q=p;p=p->next;}If(p==NULL) cout<<“要删除的结点不存在”;elseq->next=p ->next;delete(p);}}//在头指针head所指的单链表中,在值为x的结点之后插入值为y的结点void insert(1ink *head,elemtype x,elemtype y){ link *p, *s;s=new link;s->data=y;if(head->next==NULL) //链表为空{head->next=s;s->next=NULL:}p=Locate(head,x);//调用查找算法‘if(p==NULL)cout<<”插入位置非法”:else(s->next=p->next;p->next=s;}}//将单链表p中所有值为x的元素修改成y void change(1ink *p,elemtype x,elemtype y) {link *q;q=p->next;while(q!=NULL){ if(q->data==x) q->data=y;q=q->next;}}void count(1ink *h) //统计单链表中结点个数{1ink *p;int n=0;p=h->next;while(p!=NULL){n++;p=p->next;}return n;}void main(){ int n;elemtype x,y;link *p, *q;p=hcreat(); //头插法建立链表print(p); //输出刚建立的单链表cout<<”请输入要删除的元素”;cin>>y;deletel(p,y);print(p); //输出删除后的结果cout<<”请输入插入位置的元素值(将待插元素插入到它的后面)”; cin>>x;cout<<”请输入待插元素值”;cin>>y;insert(p,x,y);print(p); //输出插入后的结果cout<<”请输入要修改前、后的元素值”;cin>>x>>y;change(p,x,y);print(p);cout<<”请输入要查找的元素值”;cin>>x;q=Locate(p,x);if(q==NULL)cout<<x<<”不在表中,找不到!”<<endl;else cout<<x<<”在表中,已找到!”<<endl;n=count(p);cout<<”链表中结点个数为:”<<n<<endl:}//单链表的建立(尾插法)、插入、删除、查找、修改、计数、输出#include<iostream.h>#define elemtype intstruct link{ elemtype data;//元素类型link *next;//指针类型,存放下-个元素地址};//尾插法建立带头结点的单链表link *rcreat(){link *s, *p, *r;elemtype i;cout<<”输入多个结点数值(用空格分隔),为0时算法结束”; cin>>i;p=r=new link;p->next=NULL;while(i){s=new link;s->data=i;r->next=s;r=s;cin>>i; }r->next=NULL;return p;}//输出单链表void print(1ink *head){link *p;p=head->next;while(p->next!=NULL){cout<<p->data<<"->”; //输出表中非最后一个元素p=p->next;)cout<<p->data; //输出表中最后一个元素cout<<endl;}link *Locate(1ink *head,int x) ∥在单链表中查找第x个结点 {link *p;p=head;int j=0;while((p!=NULL)&&(j<x)){p=p->next; j++;}return p;}void delete I(1ink *head,elemtype x)//在head为头指针的单链表中,删除值为x的结点{link *p, *q;q=head;p=head->next;while((p!=NULL)&&(p->data!=x)){q=p;p=p->next;)if(p==NULL)cout<<”要删除的结点不存在“;else{q->next=p->next;delete(p);} }void insert(1ink *head,int x,elemtype y)//在头指针head所指单链表中,在第x个结点之后插入值为y的结点{link *p, *s;s=new link;s->data=y;if(head->next==NULL)//链表为空{head->next=s;s->next=NULL:}p=Locate(head,x); //调用查找算法if(p==NULL)cout<<”插入位置非法”;else{s->next=p->next;p->next=s;}}void change(1ink *p,elemtype x,elemtype y){∥将单链表P中所有值为x的元素改成值为ylink *q;q=p->next;while(q!=NULL){if(q->data==x)q->data=y;q=q->next;}}void count(1ink *h) //统计单链表中结点个数(1ink *p;int n=0;p=h->next;while(p!=NULL){n++;p=p->next;}retum n;}void main(){ int n;link p,q;p=rcreat();//尾插法建立链表print(p); //输出刚建立的单链表cout<<”请输入要删除的元素”;cin>>y;deletel(p,y);print(p); //输出删除后的结果cout<<”请输入插入位置”;cin>>x;cout<<”请输入待插元素值”;cin>>y;insert(p,x,y);print(p); //输出插入后的结果cout<<”请输入修改前、后的元素值”;cin>>x>>y;change(p,x,y);print(p);cout<<“请输入要查找的元素值”;cin>>x;q=Locate(p ,x);if(q==NULL)cout<<x<<”不在表中,找不到!”<<endl;else cout<<x<<”在表中,已找到!”<<endl;n=count(p);cout<<”链表中结点个数为:”<<n<endl;}六、选作实验试设计一元多项式相加(链式存储)的加法运算。

数据结构实验—图实验报告

数据结构实验—图实验报告

数据结构实验报告目的要求1.掌握图的储藏思想及其储藏实现。

2.掌握图的深度、广度优先遍历算法思想及其程序实现。

3.掌握图的常有应用算法的思想及其程序实现。

实验内容1.键盘输入数据,建立一个有向图的毗邻表。

2.输出该毗邻表。

3.在有向图的毗邻表的基础上计算各极点的度,并输出。

4.以有向图的毗邻表为基础实现输出它的拓扑排序序列。

5.采用毗邻表储藏实现无向图的深度优先递归遍历。

6.采用毗邻表储藏实现无向图的广度优先遍历。

7.在主函数中设计一个简单的菜单,分别调试上述算法。

源程序:主程序的头文件:队列#include <stdio.h>#include <stdlib.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define OVERFLOW -2typedef int QElemType;typedef struct QNode{//队的操作QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct {QueuePtr front;QueuePtr rear;}LinkQueue;void InitQueue(LinkQueue &Q){//初始化队列Q.front =Q.rear =(QueuePtr)malloc(sizeof(QNode));if(!Q.front) exit(OVERFLOW);//储藏分配失败Q.front ->next =NULL;}int EnQueue(LinkQueue &Q,QElemType e) //插入元素 e 为 Q 的新的队尾元素{QueuePtr p;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,QElemType &e) //删除 Q 的队头元素,用 e 返回其值{ if(Q.front ==Q.rear ) return ERROR;QueuePtr p;p=Q.front ->next;e=p->data;Q.front->next=p->next ;if(Q.rear==p) Q.rear =Q.front ;free(p);return OK;}主程序:#include <stdio.h>#include<stdlib.h>#include"duilie.h"#define TRUE 1#define FALSE 0#define Status int#define MAX_VERTEX_NUM 8/* 极点最大个数*/#define VertexType char /* 极点元素种类*/enum BOOlean {False,True};BOOlean visited[MAX_VERTEX_NUM];//全局变量——接见标志数组typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;int weight; /* 边的权 */}ArcNode;/* 表结点 */typedef struct VNode{ int degree,indegree;/* 极点的度,入度*/VertexType data;ArcNode *firstarc;}VNode/* 头结点 */,AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;/* 极点的本质数,边的本质数*/}ALGraph;//建立图的毗邻表void creat_link(ALGraph *G){int i,j; ArcNode*s;printf(" 请依次输入极点数、边数:");scanf("%d%d",&G->vexnum,&G->arcnum);for (i=0;i<G->vexnum;i++){G->vertices[i].data='A'+i; G->vertices[i].firstarc=NULL;}for (i=0;i<G->vexnum;){ printf(" 请输入极点的数组坐标 (若退出,请输入 -1) : ");scanf("%d",&i);if(i==-1) break;printf(" 请输入极点所指向下一个极点的数组坐标:");scanf("%d",&j);s=(ArcNode *)malloc(sizeof(ArcNode));s->adjvex=j;s->nextarc=G->vertices[i].firstarc;G->vertices[i].firstarc=s;}}//输出毗邻表void visit(ALGraph G){int i; ArcNode *p;printf("%4s%6s%18s\n","NO","data","adjvexs of arcs");for (i=0;i<G.vexnum;i++){printf("%4d%5c",i,G.vertices[i].data);for(p=G.vertices[i].firstarc;p;p=p->nextarc)printf("%3d",p->adjvex);printf("\n");}}//计算各极点的度及入度void cacu(ALGraph *G){ArcNode *p;int i;for (i=0;i<G->vexnum;i++){G->vertices[i].degree=0;G->vertices[i].indegree=0;}//度与初度初始化为零for (i=0;i<G->vexnum;i++)for(p=G->vertices[i].firstarc;p;p=p->nextarc){G->vertices[i].degree++;G->vertices[p->adjvex].degree++;G->vertices[p->adjvex].indegree++;}}void print_degree(ALGraph G){int i;printf("\n Nom data degree indegree\n");for (i=0;i<G.vexnum;i++)printf("\n%4d%5c%7d%8d",i,G.vertices[i].data,G.vertices[i].degree,G.vertices[i].indegree);printf("\n");}//拓扑排序Status TopologiSort(ALGraph G){int i,count,top=0,stack[50];ArcNode *p;cacu(&G);print_degree(G);printf("\nTopologiSort is \n");for(i=0;i<G.vexnum;i++)if(!G.vertices[i].indegree) stack[top++]=i;count=0;while(top!=0){i=stack[--top];if (count==0) printf("%c",G.vertices[i].data);else printf("-->%c",G .vertices[i].data);count++;for(p=G.vertices[i].firstarc;p;p=p->nextarc)if (!--G.vertices[p->adjvex].indegree)stack[top++]=p->adjvex;}if (count<G.vexnum)return(FALSE); else return(TRUE);}//在图 G 中搜寻第v 个极点的第一个毗邻极点int FirstAdjVex(ALGraph G ,int v){if(!G.vertices[v].firstarc) return 0;else return(G.vertices[v].firstarc->adjvex);}//在图 G 中搜寻第v 个极点的有关于u 的下一个毗邻极点int NextAdjVex(ALGraph G,int v,int u){ArcNode *p;p=G.vertices[v].firstarc;while(p->adjvex!=u) p=p->nextarc; //在极点v的弧链中找到极点u if(p->nextarc==NULL) return 0;// 若已经是最后一个极点,返回0else return(p->nextarc->adjvex);// 返回下一个毗邻极点的序号}//采用毗邻表储藏实现无向图的深度优先递归遍历void DFS(ALGraph G ,int i){int w;visited[i]=True;// 接见第 i 个极点printf("%d->",i);for(w=FirstAdjVex(G ,i);w;w=NextAdjVex(G,i,w))if(!visited[w]) DFS(G ,w); // 对还没有接见的毗邻极点w 调用 DFS}void DFSTraverse(ALGraph G){int i;printf("DFSTraverse:");for(i=0;i<G .vexnum;i++) visited[i]=False; //接见标志数组初始化for(i=0;i<G .vexnum;i++)if(!visited[i]) DFS(G ,i); // 对还没有接见的极点调用DFS}//按广度优先非递归的遍历图G,使用辅助队列Q 和接见标志数组visited void BFSTraverse(ALGraph G){int i,u,w;LinkQueue Q;printf("BFSTreverse:");for(i=0;i<G .vexnum;i++)visited[i]=False; // 接见标志数组初始化InitQueue(Q); //初始化队列for(i=0;i<G .vexnum;i++)if(!visited[i]){visited[i]=True;//接见极点iprintf("%d->",i);EnQueue(Q,i);// 将序号 i 入队列while(!(Q.front ==Q.rear)) //若队列不空,连续{DeQueue(Q,u);//将队头元素出队列并置为ufor(w=FirstAdjVex(G ,u);w;w=NextAdjVex(G ,u,w))if(!visited[w])//对 u 的还没有接见的毗邻极点w 进行接见并入队列{ visited[w]=True;printf("%d->",w);EnQueue(Q,w);}}}}void main(){ALGraph G;int select;printf("图的有关操作实验\n ");do{printf("\n1 创办一个有向图的毗邻表 2 输出该毗邻表\n");printf("3. 输出该有向图的度和入度 4.输出该有向图拓扑排序序列\n");printf("5. 创办一个无向图的毗邻表 6.深度优先递归遍历该无向图\n");printf("7. 广度优先遍历该无向图0.退出\n");printf(" 请输入选择:");scanf("%d",&select);switch(select){case 1:printf("\n 创办一个有向图的毗邻表:\n");creat_link(&G);break;case 2:printf("\n 输出该毗邻表:\n");visit(G);break;case 3:printf("\n 输出该有向图的度和入度:\n");cacu(&G);print_degree(G);break;case 4:printf("\n 输出该有向图拓扑排序序列:\n");if(!TopologiSort(G))printf("Toposort is not success!");break;case 5:printf("\n 创办一个无向图的毗邻表: \n");creat_link(&G);break;case 6:printf("\n深度优先递归遍历该无向图: \n");DFSTraverse(G);break;case 7:printf("\n 广度优先遍历该无向图:\n");BFSTraverse(G);break;case 0:break;default:printf(" 输入选项错误!重新输入!\n");}}while(select);}运行结果截图:1.主菜单界面:2.创办一个有向图的领接表3.输出该毗邻表4.在有向图的毗邻表的基础上计算各极点的度,并输出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

附件2:北京理工大学珠海学院实验报告ZHUHAI CAMPAUS OF BEIJING INSTITUTE OF TECHNOLOGY 实验题目图及其应用实验时间 2011.5.10一、实验目的、意义(1)熟悉图的邻接矩阵(或邻接表)的表示方法;(2)掌握建立图的邻接矩阵(或邻接表)算法;(3)掌握图的基本运算,熟悉对图遍历算法;(4)加深对图的理解,逐步培养解决实际问题的编程能力二、实验内容及要求说明1:学生在上机实验时,需要自己设计出所涉及到的函数,同时设计多组输入数据并编写主程序分别调用这些函数,调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。

具体要求:(1)建立图的邻接矩阵(或邻接表);(2)对其进行深度优先及广度优先遍历。

三、实验所涉及的知识点1.创建一个图: CreateUDN(MGraph &G)2.查找v顶点的第一个邻接点: FirstAdjVex(MGraph G,int v)3. 查找基于v顶点的w邻接点的下一个邻接点: NextAdjVex(MGraph G,int v,int w)4.图的矩阵输出: printArcs(MGraph G)5:顶点定位: LocateVex(MGraph G,char v)6. 访问顶点v输出: printAdjVex(MGraph G,int v)7. 深度优先遍历: DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))8. 广度优先遍历BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))9. DFS,从第v个顶点出发递归深度优先遍历图G: DFS(MGraph G,int v)四、实验记录1.对顶点的定位其数组下标,利用了找到之后用return立即返回,在当图顶点多的情况下节省了搜索时间,程序如下//对顶点v定位,返回该顶点在数组的下标索引,若找不到则返回-1int LocateVex(MGraph G,char v){for (int i=0;i<G.vexnum;i++){if(v == G.vexs[i])return i;}return -1;}2,定义里一个全局的函数指针变量,同时在深度优先遍历中加入一个函数指针参,调用时,将传如的函数赋值给全局的函数指针,这样在之后循环调用DFS的时候就不用将函数传给DFS函数了,程序如下://深度优先遍历void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//将函数复制给全局的函数指针变量,待调用DFS时使用VisitFunc = Visit;int v;//将访问标记初始化为falsefor (v=0;v<G.vexnum;v++)visited[v] = false;for (v=0;v<G.vexnum;v++)//对尚未访问即访问标记为false的顶点调用DFSif (!visited[v]) DFS(G,v);}五、实验结果及分析预备输入的图结构如下:顶点为:a ,b ,c ,d ,e弧及其权值为:a,b,2a,c,3 b,d,4 b,e,2 d,e,1结果如下:1.图的创建,先输入顶点个数与边数,如图 4.1.1,接着输入各顶点的值,如图4.1.2,最后输入三条边依附的顶点以及权值,当输入的顶点不在图中时,会提示重新输入,如图4.1.3图4.1.1图4.1.2图4.1.3 abc d e2 31 422.图的矩阵输出,如图4.2图4.23.深度优先遍历图,输出序列,如图4.3图4.34.广度优先遍历图,输出序列,如图4.4图4.4六、总结与体会图,是一种较线性表和树更为复杂的数据结构将其用深度遍历后,可以变成一棵树,或者一个森林。

和树的遍历相类似,都利用了递归的方法,逐个搜索输出。

用邻接矩阵表示图,形象地体现出顶点与顶点之间的紧密关系。

七、程序清单(包含注释)#include "stdio.h"#include "limits.h" //INT_MAX头文件#include "windows.h" //boolean头文件#define INFINITY INT_MAX#define MAX_VERTEX_NUM 20#define OVERFLOW -1#define OK 1#define ERROR 0typedef int Status;typedef enum {DG,DN,UDG,UDN} GraphKind;typedef int VRType;typedef char VertexType;typedef char* InfoType;typedef int QElemType;//边信息typedef struct ArcCell{VRType adj; //1或0表示是否邻接,对带权图,则为权值类型InfoType *info;}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//图结构typedef struct {VertexType vexs[MAX_VERTEX_NUM]; //定点向量AdjMatrix arcs; //邻接矩阵,为一二维数组int vexnum,arcnum; //图的当前顶点数和弧数GraphKind kind; //图的种类标志}MGraph;//辅助队列typedef struct QNode{QElemType data; //数值域struct QNode *next; //指针域}QNode, *QueuePtr;typedef struct{QueuePtr front; //队头QueuePtr rear; //队尾}LinkQueue;//初始化队列Status InitQueue(LinkQueue &Q){Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if (!Q.front){printf("内存分配失败!");exit(OVERFLOW);}Q.front->next = NULL;return OK;}//插入元素到队尾Status EnQueue(LinkQueue &Q,QElemType e){QueuePtr p = (QueuePtr)malloc(sizeof(QNode));if (!p){printf("\n内存分配失败!");exit(OVERFLOW);}p->data = e;p->next = NULL;Q.rear->next = p;Q.rear = p;return OK;}//队列判空Status QueueEmpty(LinkQueue Q){return Q.front == Q.rear;}//销毁队列Status DestroyQueue(LinkQueue &Q){while (Q.front){Q.rear = Q.front->next;free(Q.front);Q.front = Q.rear;}return OK;}//删除队头元素Status DeQueue(LinkQueue &Q,QElemType &e){if (QueueEmpty(Q)){printf("\n队列为空!");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;}//对顶点v定位,返回该顶点在数组的下标索引,若找不到则返回-1 int LocateVex(MGraph G,char v){for (int i=0;i<G.vexnum;i++){if(v == G.vexs[i])return i;}return -1;}//create a graphStatus CreateUDN(MGraph &G){G.kind = UDN;printf("输入顶点个数和边数(如:4,3):");scanf("%d,%d",&G.vexnum,&G.arcnum);//判断是否超过顶点最大个数while(G.vexnum>MAX_VERTEX_NUM){printf("最大顶点为20,重新输入(如:4,3):");scanf("%d,%d",&G.vexnum,&G.arcnum);}printf("\n依次输入顶点向量值\n");int i;for (i=0;i<G.vexnum;i++){//清空缓冲区fflush(stdin);printf("第%d个:",i+1);scanf("%c",&G.vexs[i]);}//初始化邻接矩阵for (i=0;i<G.vexnum;i++){for (int j=0;j<G.vexnum;j++){G.arcs[i][j].adj = INFINITY;G.arcs[i][j].info = NULL;}}char front,rear;int values;printf("\n输入依附两个顶点的边及其权值<如,a,b,1>\n");for(i=0;i<G.arcnum;i++){printf("第%d条:",i+1);//清空缓冲区fflush(stdin);scanf("%c,%c,%d",&rear,&front,&values);int m,n;//定位两顶点在vexs数组中的索引m = LocateVex(G,rear);n = LocateVex(G,front);if(m==-1||n==-1){printf("输入顶点或不在此图中,请重新输入!\n");i--;continue;}//赋予对应矩阵位置的权值,以及对称弧的权值G.arcs[m][n].adj = values;G.arcs[n][m].adj = values;}return OK;} //CreateUDG//矩阵输出void printArcs(MGraph G){int i;printf(" ");//输出第一行的顶点向量for (i=0;i<G.vexnum;i++){printf(" %c",G.vexs[i]);}for (i=0;i<G.vexnum;i++){printf("\n\n%c",G.vexs[i]);for (int j=0;j<G.vexnum;j++){if(G.arcs[i][j].adj==INFINITY)printf(" ∞");elseprintf(" %d",G.arcs[i][j].adj);}}printf("\n");}//访问顶点v输出Status printAdjVex(MGraph G,int v){printf("%c ",G.vexs[v]);return OK;}//查找v顶点的第一个邻接点Status FirstAdjVex(MGraph G,int v){//查找与顶点v的第一个邻接点,找到后立即返回其索引,若找不到,则返回-1 for (int i=1;i<G.vexnum;i++){if(G.arcs[v][i].adj!=INFINITY)return i;}return -1;}//查找基于v顶点的w邻接点的下一个邻接点Status NextAdjVex(MGraph G,int v,int w){//查找基于顶点v的w邻接点的下一个邻接点,找到之后立即返回其索引,若找不到,则返回-1for (int i=w+1;i<G.vexnum;i++){if (G.arcs[v][i].adj!=INFINITY)return i;}return -1;}//创建访问标志全局变量boolean visited[MAX_VERTEX_NUM];//函数指针变量Status (* VisitFunc)(MGraph G,int v);//DFS,从第v个顶点出发递归深度优先遍历图Gvoid DFS(MGraph G,int v){visited[v] = TRUE;//访问第v个顶点VisitFunc(G,v);for (int w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){if (!visited[w])DFS(G,w);}}//深度优先遍历void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//将函数复制给全局的函数指针变量,待调用DFS时使用VisitFunc = Visit;int v;//将访问标记初始化为falsefor (v=0;v<G.vexnum;v++)visited[v] = false;for (v=0;v<G.vexnum;v++)//对尚未访问即访问标记为false的顶点调用DFSif (!visited[v]) DFS(G,v);}//广度优先遍历void BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//按广度优先非递归遍历图G,使用辅助队列Q和访问标志数组Visitedint v;int u;//将访问标记数组初始化为falsefor (v = 0;v<G.vexnum;v++)visited[v] = FALSE;//创建辅助队列QLinkQueue Q;InitQueue(Q);for (v = 0;v<G.vexnum;v++)//判断顶点V是否被访问if (!visited[v]){//将第一次访问的顶点对应的访问标记数组位置赋值为TRUEvisited[v] = TRUE;//输出顶点vVisit(G,v);EnQueue(Q,v);while (!QueueEmpty(Q)){//按入队序列取出顶点,便于查找此顶点的邻接点DeQueue(Q,u);//查找当前顶点邻接点for (int w=FirstAdjVex(G,u);w>=0;w = NextAdjVex(G,u,w))if (!visited[w]){visited[w] =TRUE;Visit(G,w);EnQueue(Q,w);}}}//销毁队列DestroyQueue(Q);}void main(){printf("====图的创建及其应用====\n");//创建一个图MGraph G;CreateUDN(G);//用邻接矩阵输出图printf("\n图的邻接矩阵输出如下:\n");printArcs(G);//深度优先遍历printf("\n深度优先遍历序列:\n");DFSTraverse(G,printAdjVex);printf("\n");//广度优先遍历printf("\n广度优先遍历序列:\n");BFSTraverse(G,printAdjVex);printf("\n");}11。

相关文档
最新文档