当前位置:文档之家› 大二上课程设计最终版

大二上课程设计最终版

《数据结构》课程设计报告学号:20131000678班级序号:113131姓名:孙国欢指导老师:张唯成绩:中国地质大学(武汉)信息工程学院遥感系2015年1月总体介绍这是大二上学习了数据结构后的课程设计。

数据结构这门课相对于大一所学习的计算机高级程序语言设计更为复杂,此次课程设计主要考察的三个知识点分别为:堆栈、搜索树、图。

这三个是数据结构中最重要并且考验应用能力的三个知识点。

我开始拿到题目只有想出流程做法,怎么写代码仍是一头雾水,最后随着课程设计的深入,多与老师研究探讨之后开始有点眉目了。

通过对书上实例的反复翻阅学习,我对数据结构又有了更深入的认识,三项知识点的应用也更加熟路。

实习题目一火山喷发模拟1、功能需求火山喷发时,岩浆会随着地势的走向逐步扩散,岩浆经过的区域,即为当前火山喷发的灾害影响范围。

设计合理的数据结构,计算火山灾害的影响面积,并给出灾害影响范围图。

2、数据结构及算法本题重点考察数组和堆栈的使用。

使用高程矩阵描述火山周边地形,矩阵中每个像元占有一定的面积,像元值为当前位置的海拔高度,其中最高的位置即为火山口。

火山喷发时,从火山口源源不断地涌出岩浆,岩浆会流向火山口周边所有地势较低的位置。

由于是矩阵形式的地形,每个像元有固定的八个周边位置,即上下左右及其对角线方向的像元。

而某个位置一旦被岩浆覆盖,又会继续流向自身周边所有地势较低的位置。

依次循环,最终岩浆经过的像元,即为火山喷发的灾害影响范围。

每个像元的周围八个像元需要全部判别,因此需要采用堆栈来记录每次判断的像元信息。

由于每个像元占有一定面积,火山灾害的影响面积即为岩浆经过的像元个数乘以像元面积,灾害影响范围图可以使用0、1的矩阵,即受灾位置为1,未受灾位置为0来表示。

【实现过程】(1)思想:这道题的关键是判别火山口的位置以及高程,随后利用递归原理将判别高低的结果输出到文本中。

难点的解决可以参考书中关于回溯法解决迷宫的问题,总体来说并不困难。

(2)程序实例:#include<iostream>using namespace std;struct offsets //位置在直角坐标下的偏移{ int a,b; //a,b是x,y方向的偏移char *dir; //dir是方向};offsetsmove[8]={{-1,0,"N"},{-1,1,"NE"},{0,1,"E"},{1,1,"SE"},{1,0,"S"},{1,-1,"SW"},{0,-1,"W"},{-1,-1,"NW"}};; //各个方向的偏移表int Maze[5][5]; //模拟火山二维矩阵int mark[5][5]; //访问标志数组int Seekpath(int x,int y){char *d;int g,h;mark[x][y]=1;for (int c=0;c<5;c++){g=x+move[c].a;h=y+move[c].b;d=move[c].dir;if (mark[g][h]==0&&Maze[g][h]<Maze[x][y]){mark[g][h]=1;if(Seekpath(g,h))return 1;}}return 0;};void main(void){int i,j;cout<<"请输入一个模拟火山的5*5的矩阵:"<<endl; for(i=0;i<5;i++){for(j=0;j<5;j++){cin>>Maze[i][j];mark[i][j]=Maze[i][j];}cout<<endl;}int max=0,l,k;for ( i=0;i<5;i++)for ( j=0;j<5;j++){if ( max<Maze[i][j]){max=Maze[i][j];l=i;k=j;}}for (i=0;i<5;i++) //初始化访问函数for (j=0;j<5;j++)mark[i][j]=0;Seekpath(l,k);for (i=0;i<5;i++){ for (j=0;j<5;j++){ cout<<mark[i][j]<<" ";}cout<<endl;}cout<<"火山口高度为:"<<max<<" 位于:"<<"第"<<l+1<<"行"<<"第"<<k+1<<"列"<<endl; }(3)运行结果:我没有解决像元面积的问题,想法是标记1的数量调用一个函数求得面积,最终没有写进去有点遗憾。

希望在以后的学习里能够善始善终,不畏难关。

(4)重点问题:有的同学采用的文件流读入火山矩阵信息,这只是一个小方面。

最终要的内容是如何判别最高点即为火山口的位置和进行八个方向的比较。

肯定是要利用堆栈来记录每次判断的像元信息,不能完全理解的话参照书上关于回溯法解决迷宫难题的相关讲解。

设置一个矩阵作为一个n维数组,调用一个前进方向函数,给出各个方向的偏移量。

通过位移标记数组并且保存行走路径,然后再递归就全部标记好了。

(5)算法分析:offsetsmove[8]={{-1,0,"N"},{-1,1,"NE"},{0,1,"E"},{1,1,"SE"},{1,0,"S"},{1,-1,"SW"},{0,-1,"W"},{-1,-1,"NW"}};; //各个方向的偏移表int g,h;mark[x][y]=1;for (int c=0;c<5;c++){g=x+move[c].a;h=y+move[c].b;d=move[c].dir;if (mark[g][h]==0&&Maze[g][h]<Maze[x][y]){mark[g][h]=1;if(Seekpath(g,h))return 1;}}这是有关回溯法的重要内容,上面是定义位移,下面是对数组元素偏移周围的大小判断后的标记,最后两句表示递归,这样就基本解决主要问题了。

实习题目二电子同学录1、功能需求编程实现一个小工具,支持文本格式同学信息的输入输出和查询。

同学信息至少应该包含姓名、性别、身份证号、班级、年龄、家庭住址等,其他如EMAIL等可根据实际情况酌情添加。

具体功能如下:(1)、信息管理(1)、从文本文件中批量导入多个同学信息;(2)、添加、编辑和删除单个同学信息,提供编辑界面;(3)、支持自定义群组的建立,能够将同学按照不同类型进行分组,如大学同学、高中同学等,具体分组方式和操作可参看QQ,一个同学可以同时存在于多个不同的分组中;(2)、信息查询提供查询条件的选择和输入以及查询结果的显示窗口,要求使用BST或AVL树动态创建搜索结构。

(1)、根据姓名查询同学,支持模糊查询,如丁一、丁二,输入“丁”字即可同时查询到。

(2)、根据身份证号查询同学,支持模糊查询;(3)、根据其他属性查询同学,支持模糊查询;(4)、根据群组查询同学,显示查询到的所有记录。

(5)、查询结果输出至文本文件。

2、数据结构及算法本题重点考察线性表和搜索树的使用。

设定合理的结构来存储同学的基本信息,请注意不同信息的数据类型。

信息编辑功能主要涉及线性表的具体添加和删除操作。

群组信息需要单独管理,群组和同学信息之间可以使用指针来连接,也可以通过在同学信息中添加属性项来实现。

信息查询功能主要涉及搜索树的动态建立和查找,根据用户选定的属性项,建立相应的搜索树,根据属性内容的不同,也可以采用哈希表的方式来进行相应的搜索设计,但必须实现动态的构建和销毁。

例如,姓名可以采用形式笔画或拼音排序,建立相应的BST树,而数字类型的属性字段如年龄等则可以采用取余的方式建立哈希函数。

【实现过程】(1)思想:这道题的关键是搜索树的建立。

我一开始思考这道题我想假如利用大一学的也能写的七七八八,但是还是简单的C++知识没有利用数据结构。

所以通过上网查询和老师指导,我逐步摸索出要点。

定义好数据表和数据录,逐步输入文本,然后根据要求编写相关的调用函数,一步一步来,虽然可能会很复杂但是理清脉络要想实现也并不困难。

(2)程序实例:#include<iostream>#include<string>#include<iomanip>#include<fstream>#include<windows.h>using namespace std;typedef struct//定义数据结构{string num;string name;string sex;string phone;string addr;}DataType;typedef struct node{DataType data;struct node *next; //定义顺序表节点}ListNode;typedef ListNode *LinkList;class StudentRecords //类{public:StudentRecords(){head=new ListNode;head->next=NULL;}~StudentRecords();void Build(); //功能相关函数void Add();void Check();void Delete();void PrintList();void cin_file(char*filename);void Preservation_file();private:LinkList head; //头结点};void StudentRecords::Build(){string NUM;bool flag=false;ListNode *p; // 存放后继元素的地址cout<<"分别输入编号,姓名,性别,电话,地址(输入0 结束通信录的建立):"<<endl; while(!flag){cout<<"编号:";cin>>NUM;if(NUM>"0"){ p=new ListNode; //判断是否存在之后录入p->data.num=NUM;cout<<"姓名:";cin>>p->;cout<<"性别:";cin>>p->data.sex;cout<<"电话:";cin>>p->data.phone;cout<<"地址:";cin>>p->data.addr;p->next=head->next;head->next=p;}else break; }cout<<endl;}StudentRecords::~StudentRecords() //类的析构函数{ListNode *p,*q;p=head;q=p->next;delete p;while(q){p=q;q=p->next;delete p;} //判断}void StudentRecords::Add() //继续添加{ListNode *p;bool flag=true;while(flag){p=new ListNode;cout<<"分别输入编号,姓名,性别,电话,地址:"<<endl;cout<<"编号:";cin>>p->data.num;cout<<"姓名:";cin>>p->;cout<<"性别:";cin>>p->data.sex;cout<<"电话:";cin>>p->data.phone;cout<<"地址:";cin>>p->data.addr;p->next=head->next;head->next=p;cout<<endl;cout<<"是否继续添加?(Y/N):";char YN;cin>>YN;if(YN=='Y')flag=true;else flag=false;}}void StudentRecords::Check() //查找{ListNode *p,*q;int i;bool flag1,flag2,flag3,flag;flag=true;char YN='Y';string NUM;string NAME;while(flag){if(!head->next){cout<<"通信录为空!"<<endl;break;}else{while(YN=='Y'){flag3=false;cout<<"请选择查询的方式(1编号,2姓名):";cin>>i;switch(i){case 1:cout<<"请输入编号:";cin>>NUM;break;case 2:cout<<"请输入姓名:";cin>>NAME;break;default:cout<<"好像输错了亲!"<<endl;flag3=true;break; }if(!flag3){p=head->next;flag1=false;while(p){flag2=false;switch(i){case 1:if(NUM==p->data.num){flag2=flag1=true;q=p;}p=p->next;break;case 2:if(NAME==p->){flag2=flag1=true;q=p;}p=p->next;break;default:break;}if(flag2){cout<<"该学生信息如下:"<<endl;cout<<"编号:"<<q->data.num<<endl;cout<<"姓名:"<<q-><<endl;cout<<"性别:"<<q->data.sex<<endl;cout<<"电话:"<<q->data.phone<<endl;cout<<"地址:"<<q->data.addr<<endl;}}cout<<endl;if(!flag1)cout<<"没有这个人!"<<endl;cout<<"请问是否继续查询?(Y/N):";cin>>YN;if(YN=='Y')flag=true;else flag=false;}}}cout<<endl;}}void StudentRecords::Delete() //删除信息{ListNode *p,*q;string NUM;char YN='Y';bool flag,flag1;flag1=true;while(flag1){while( YN=='Y'){ flag=false; p=head;q=p->next;if(!q){cout<<"通信录为空!"<<endl;flag1=false; break;}cout<<"输入删除编号:";cin>>NUM;while(q){if(NUM==q->data.num){cout<<"删除学生信息如下:"<<endl;cout<<"编号:"<<q->data.num<<endl;cout<<"姓名:"<<q-><<endl;cout<<"性别:"<<q->data.sex<<endl;cout<<"电话:"<<q->data.phone<<endl;cout<<"地址:"<<q->data.addr<<endl;p->next=q->next;delete q;flag=true;break;}else {p=p->next; q=p->next;}}if(!flag) cout<<"没有这个人!"<<endl;cout<<"是否继续进行删除?(Y/N):";cin>>YN;if(YN=='Y')flag1=true;else flag1=false;}}cout<<endl;}void StudentRecords::PrintList() //显示联系人信息{ListNode *p,*q,*s,*Max,*Min,*first;int count=0;if(head->next){first=new ListNode;s=first;cout<<"通信录的全部信息如下:"<<endl<<endl;cout<<"****编号"<<"***********姓名"<<"**********性别"<<"**********电话"<<"**************地址***********"<<endl;while(head->next){Min=head->next ;Max=Min->next ;q=head;while(Max&&Min){if(Max->data .num <Min->data .num ){Min=Max;Max=Max->next ;}else Max=Max->next ;}while(q->next !=Min)q=q->next ;q->next =Min->next;s->next=Min;s=Min;s->next =NULL;}delete head;head=first;p=head->next;while(p){cout<<setw(8)<<p->data.num<<setw(17)<<p-><<setw(13)<<p->data.sex<<setw(16)<<p->data.phone<<setw(21)<<p->data.addr<<endl;p=p->next;count++;}cout<<endl<<"同学总人数为:"<<count<<endl;}else cout<<"通信录为空!"<<endl;cout<<endl;}void StudentRecords::cin_file(char*filename){ifstream infile(filename,ios::in);if(!infile){cerr<<"open error!"<<endl;exit(1);}ListNode ch,* p;while(infile>>ch.data.num){ p=new ListNode;infile>>>>ch.data.sex>>ch.data.phone>>ch.data.addr; p->data.num=ch.data.num;p->=;p->data.sex=ch.data.sex;p->data.phone=ch.data.phone;p->data.addr=ch.data.addr;p->next=head->next;head->next=p;}infile.close();}void StudentRecords::Preservation_file(){ofstream outfile("RD.txt",ios::out);if(!outfile){cerr<<"open error!"<<endl;exit(1);}ListNode * p;p=head->next;while(p){outfile<<setw(8)<<p->data.num<<setw(17)<<p-><<setw(13)<<p->data.sex<<setw(16)<<p->data.phone<<setw(22)<<p->data.addr<<endl;p=p->next;}cout<<"记录已保存!"<<endl<<endl;outfile.close();}int main(){StudentRecords RD;system("color 3");int n=1;fstream outfile("RD.txt",ios::out|ios::app); if(!outfile){cerr<<"open error!"<<endl;abort();}outfile.close();RD.cin_file("RD.txt");while(n){int m;cout<<" 欢迎进入孙国欢的通讯录 "<<endl;cout<<" 1.建立 "<<endl;cout<<" 2.添加 "<<endl;cout<<" 3.查询 "<<endl;cout<<" 4.删除 "<<endl;cout<<" 5.输出 "<<endl;cout<<" 6.保存 "<<endl;cout<<" 0.退出管理系统 "<<endl;cout<<"请输入您的选择(0--6):";cin>>m;switch(m){case 1:RD.Build();break;case 2:RD.Add();break;case 3:RD.Check();break;case 4:RD.Delete();break;case 5:RD.PrintList();break;case 6:RD.Preservation_file();break;case 0:n=0;break;default:cout<<"好像输错了!"<<endl;break;}}return 0;}(3)运行结果:这是我事先写进去的相关联系人信息首先检测是否能够输出。

相关主题