空间数据结构基础实验指导书学年度.docx
《空间数据结构基础实验指导书学年度.docx》由会员分享,可在线阅读,更多相关《空间数据结构基础实验指导书学年度.docx(37页珍藏版)》请在冰豆网上搜索。
![空间数据结构基础实验指导书学年度.docx](https://file1.bdocx.com/fileroot1/2023-1/30/4dc563c9-fb82-4115-94c5-1e7a01dfa04f/4dc563c9-fb82-4115-94c5-1e7a01dfa04f1.gif)
空间数据结构基础实验指导书学年度
《空间数据结构基础》
课程实习指导书
实习周数:
2周学分数:
2
一、实习目的
数据结构是一门重要的专业基础课,其特点是理论与实践都占据着极其重要的位置。
这门课对学生的主要要求包括要掌握各种基本数据结构的定义、抽象数据类型描述、相关的算法描述与算法的性能分析与评价,以及数据结构与算法的综合应用能力。
为了达到教学要求,以上机实验为主要形式的实践教学环节是不可缺少的。
上机实验的主要内容可分为两种,一是验证经典算法和教材中的算法例程,二是设计并检验自己设计的算法,课程中的16课时的上机实验主要是以前者为目的,而为期2周的课程实习则以后者为目的。
通过课程实习可以帮助学生正确理解所学概念,了解不同的算法特点,掌握算法性能,积累算法设计经验。
教学经验表明,学生只有通过一定时间量的算法设计和程序调试等实践活动,才能较全面和较深入地掌握数据结构的知识,在此基础上,发挥学生的想象力和创造力,设计出新颖多样的有应用价值的算法。
二、实习要求
1.通过实习,学生能够对所学的每一种数据结构正确理解,能够针对不同的问题选择合适的数据结构,在程序中将抽象数据类型实例化。
2.深刻理解典型算法的设计思想,掌握不同算法在解题策略和流程控制逻辑等方面的不同特点和实现方法。
再进一步总结并掌握计算机处理数据和解决问题的一般规律,从而能够自行设计应用算法。
3.学会对算法进行性能评价和分析,比较同一个问题的多种解法,针对具体问题能够设计出高效的算法。
4.提高学生进行程序设计的综合能力,使其从初学者进阶到较有经验和专业素质的程序设计者。
5.要求学生严格遵守实习纪律,认真开发,按时提交实习报告。
三、实习内容
参见“六、实习内容简介”中每章的“二、程序设计练习”和第六章的练习。
根据个人情况任选5~6题予以完成。
四、实习内容的时间分配
⏹先集中1天左右时间对实习进行安排;
⏹针对不同的实习项目,学生用2天左右的时间进行资料查询和开发方案设计;
⏹方案和数据结构设计完成后,利用5天左右时间进行程序编码、调试和优化;
⏹最后利用2天左右时间进行汇报讨论和提交实习报告。
五、成绩评定
本实习采取考核方式,以实习教学所占总成绩的比例为100,其中上机操作占20%,实习纪律占20%,实习报告占60%。
实验成绩折算成优、良、中、及格、不及格五个等级进行评分。
六、实习内容简介
第1章C++面向对象程序设计基础
本章实验目的:
学会用算法语言C++描述抽象数据类型,使用模板建立数据结构。
熟练掌握C++程序的编制、调试和运行方法,为本课程的实验做好准备。
学习重点:
理解数据结构的组成分为两部分,第一部分是数据集(数据元素),第二部分是在此数据集上的操作。
从面向对象的观点看,这两部分代表了对象的属性和方法。
掌握用C++描述数据结构的基本方法,即通过建立类来描述抽象数据类型。
类的数据成员提供对象属性,成员函数提供操作方法,方法是公共接口,用户通过调用方法实现对属性的访问。
一、C++面向对象程序设计范例
1.二维坐标点point的C++描述
【实验目的】用面向对象的方法定义一个简单的抽象数据结构,本例实验内容为坐标点的数据结构。
学会如何用C++语言描述数据结构和算法,理解将数据集和在此数据集上的操作分开描述的方法。
【数据结构】将坐标点数据结构定义为一个C++类Point,在其内部分别定义数据成员和成员函数。
(1)数据成员:
一个平面直角坐标系中的点有两个属性,它们是x轴上的水平坐标值和y轴上的垂直坐标值。
在Point类中,这两个属性分别由数据成员x和y来表示,定义为double类型的私有数据成员。
(2)操作方法:
定义成员函数,为类的使用者提供服务接口。
先设计允许对点对象进行的操作,再用C++描述实现操作的算法,并定义为类Point的成员函数。
在本例中提供了两个操作:
move()函数将一个Point对象移至另一位置,Show()函数输出Point对象的数据成员值。
两个构造函数,分别用于建立缺省参数的对象和带参数的对象。
【算法提示】缺省构造函数Point()将新建立的坐标点对象初始化为原点位置(0,0)。
带参数的构造函数Point(doublepx,doublepy)允许用户建立对象时指定初始坐标位置。
点对象的移动操作move()函数需要在调用时给出新位置参数。
输出坐标值为无参函数。
以下是平面直角坐标系中的点的类定义,main()函数对类Point的属性和操作进行测试。
【程序1.1】
#include
classPoint{//平面直角坐标系中的点
private:
doublex;//水平坐标值
doubley;//垂直坐标值
public:
Point(){x=0;y=0;}//缺省构造函数
Point(doublepx,doublepy){x=px;y=py;}//带参数的构造函数
voidmove(doublemx,doublemy){x=mx;y=my;}//移动位置(修改坐标值)
voidShow(){cout<<"x="<};
voidmain(){
Pointa,b(12.5,34.8);//建立两个Point对象
cout<<"点a的位置:
";
a.Show();//输出点a的坐标值
cout<<"点b的位置:
";
b.Show();//输出点b的坐标值
a.move(45.6,57.8);
cout<<"点a移动后的位置:
";
a.Show();//输出点a的坐标值
}
2.使用模板建立坐标点point的数据结构,直接表示抽象数据类型
【实验目的】将程序1.1数据结构的类型参数化(模板),实现更高层次的数据抽象。
【算法提示】Point的数据成员不使用固定的类型定义,而是用typename说明的虚拟类型名ptType作为变量的类型,在定义Point类的对象时,再用C++的基本类型将对象的数据成员的类型实例化。
这样做的好处是可以使用同一个类来定义不同数据类型的对象,提高代码的利用率。
【程序1.2】
templateclassPoint{//平面直角坐标系中的点
private:
ptTypex;//虚拟类型的水平坐标值
ptTypey;//虚拟类型的垂直坐标值
public:
Point(){x=0;y=0;}//缺省构造函数
Point(ptTypepx,ptTypepy){x=px;y=py;}//带参数的构造函数
voidmove(ptTypemx,ptTypemy){x=mx;y=my;}//移动位置(修改坐标值)
voidShow(){cout<<"x="<};
voidmain(){
Pointa(24,36);//建立整型的Point对象
Pointb(12.5,34.8);//建立浮点型的Point对象
cout<<"点a的位置:
";
a.Show();//输出点a的坐标值
cout<<"点b的位置:
";
b.Show();//输出点b的坐标值
a.move(25,18);
cout<<"点a移动后的位置:
";
a.Show();//输出点a的坐标值
b.move(45.6,57.8);
cout<<"点b移动后的位置:
";
b.Show();//输出点b的坐标值
}
注:
定义模板的关键字typename可以用class代替。
如:
templateclassPoint与例中的templateclassPoint具有相同功能。
3.利用Point类定义矩形类Rectangle
【实验目的】了解复合数据结构的描述方法。
矩形是一个包含坐标点的复合数据结构,在C++程序中将坐标点和矩形分别定义为具有继承关系的两个类,即定义矩形类Rectangle为Point的派生类。
使用派生类的形式定义一个数据结构,其主要目的是提高基类的代码利用率,并使派生类的结构得到简化。
基类和派生类的定义体现了C++继承机制的运用,最大程度地提高了数据结构的利用率。
【数据结构】派生的矩形类Rectangle有四个数据成员,其中左下角坐标点x和y由基类Point定义,派生类Rectangle能够继承下来作为自己的数据成员。
为了在派生类的成员函数中自由访问基类定义的数据成员,需要将这些数据成员定义为被保护的(protected)访问权限。
矩形的宽度width和高度height在派生类中定义。
在矩形类中这四个数据成员的访问权限是相同的。
【算法提示】
(1)基类Point定义的成员函数都可以由派生类Rectangle继承,在矩形对象中可以直接使用。
(2)若用一个点对象为新的矩形对象初始化,注意构造函数的写法。
对基类成员的赋值由基类的拷贝构造函数完成,例如利用点对象p3定义的矩形对象rt4,实际上使用了Point类的缺省拷贝构造函数。
如果基类成员初始化比较复杂,如含有内存分配等要求,就需要重新定义基类的拷贝构造函数。
【程序1.3】
#include
classPoint{//二维坐标点类
protected:
doublex,y;
public:
Point(){x=0;y=0;}//缺省构造函数
Point(doublepx,doublepy){x=px;y=py;}//带参数的构造函数
doubleGetx(){returnx;}//返回坐标点的x值
doubleGety(){returny;}//返回坐标点的y值
voidMove(doublemx,doublemy){x=mx;y=my;}//移动坐标点的位置
voidShow(){cout<<"x="<};
classRectangle:
publicPoint{//矩形类(Point的派生类,Point对象为矩形左下角的坐标点)
doublewidth,height;//矩形的宽度和高度
public:
Rectangle(){width=0;height=0;x=0;y=0;}//缺省构造函数
Rectangle(doublea,doubleb,doublec,doubled):
Point(a,b){//带参数的构造函数
width=c;
height=d;
}
Rectangle(Point&pn):
Point(pn){//带参数的构造函数,由点pn定义矩形左下角的位置
width=1;
height=1;
}
doubleArea(){returnwidth*height;}//求矩形的面积
voidSet(doublea,doubleb){x=a;y=b;}//重置矩形的左下角坐标
intPosition(Point&pt);//求点pt相对于矩形的位置,返回-1(在矩形内),
//0(在矩形边上)和1(在矩形外)
voidJudge(Point&pt);//判断点pt相对于矩形的位置,给出提示
voidShow();//输出矩形的各属性值和面积
};
intRectangle:
:
Position(Point&pt){//求点pt相对于矩形的位置
if(pt.Getx()x+width||pt.Gety()y+height)return1;//在矩形外
elseif(pt.Getx()>x&&pt.Getx()y&&pt.Gety()elsereturn0;//在矩形边上
}
voidRectangle:
:
Judge(Point&pt){
pt.Show();
Show();
switch(Position(pt)){
case0:
cout<<"点在矩形边上"<case-1:
cout<<"点在矩形内"<case1:
cout<<"点在矩形外"<}
}
voidRectangle:
:
Show(){//输出矩形的各属性值和面积
cout<<"rx="<cout<<"width="<cout<<"area="<
}
voidmain(){
Rectanglert1(0,0,6,8),rt2,rt3(rt1);//定义Rectangle对象
Pointp1(0,0),p2(6,8),p3(5,7);//定义Point对象
rt1.Show();//输出矩形rt1的属性值
rt2.Show();//输出矩形rt2的属性值
rt1.Set(3,5);//重置矩形rt1左下角的位置
rt2=rt1;//rt2复制矩形rt1
rt2.Show();
cout<<"点p1和矩形rt3:
";
rt3.Judge(p1);//判断点p1相对于矩形rt3的位置
rt3.Set(9,4);//重置矩形rt3左下角的位置
cout<<"点p2和矩形rt3:
";
rt3.Judge(p2);//判断点p2相对于矩形rt3的位置
cout<<"由p3定义的矩形rt4:
";
Rectanglert4(p3);//由p3定义的矩形rt4
rt4.Show();
}
4.定义矩形类Rectangle,作为Point的友元类
【实验目的】了解复合数据结构的另一种描述方法。
使用多个独立定义的类描述一个数据结构。
【数据结构】将坐标点和矩形分别定义为两个单独的类。
将二者配合使用。
●坐标点类Point:
定义与程序1.1相同。
●矩形类Rectangle:
定义Point对象作为数据成员。
为了能在矩形的函数中访问Point对象的成员,将Rectangle定义为Point的友元。
提示:
友元的使用对于被引用的类可以省去私有数据成员的访问接口,使程序变得更简洁。
其缺点是破坏了数据对象的封装性,有违数据隐藏的原则。
【算法提示】
(1)在此算法中使用了函数重载,如move()函数被多次定义,但各函数的作用域和权限是不同的。
(2)为了使用户的操作更简洁,使用了运算符重载(如算术和关系运算符+=和>,输出运算符<<),这是实现数据封装的常用技术。
【程序1.4】
#include
classPoint{//二维坐标点类
friendclassRectangle;//矩形类是点类的友元
friendostream&operator<<(ostream&,Rectangle&);//重载用于矩形的输出运算符
private:
doublex;
doubley;
voidmove(Point&p){x=p.x;y=p.y;}//移动坐标点的位置
public:
Point(){x=0;y=0;}//缺省构造函数
Point(doublepx,doublepy){x=px;y=py;}//带参数的构造函数
voidmove(doublemx,doublemy){x=mx;y=my;}//移动坐标点的位置
voidShow(){cout<<"x="<};
classRectangle{//矩形类
friendostream&operator<<(ostream&,Rectangle&);//重载输出运算符
private:
Pointpos;//矩形左下角的坐标点
doublewidth,height;//矩形的宽度和高度
public:
Rectangle(){pos.x=0;pos.y=0;width=0;height=0;}//缺省构造函数
Rectangle(doublexv,doubleyv,doublewv,doublelv){//带参数的构造函数
pos.x=xv;
pos.y=yv;
width=wv;
height=lv;
}
doubleArea(){returnwidth*height;}//求矩形的面积
voidmove(Point&pt){pos.move(pt);}//移动矩形的左下角坐标
voidset(doublea,doubleb){width=a;height=b;}//重置矩形的宽度和高度
intposition(Point&pt);//求点pt相对于矩形的位置,返回-1(在矩形内),0(在矩形边上)和1(在矩形外)
voidjudge(Point&pt);;//判断点pt相对于矩形的位置,给出提示
voidShow();//输出矩形的各属性值
voidoperator+=(Rectanglea);//重载算术运算符“+=”
intoperator>(Rectanglea);//重载关系运算符“>”
};
intRectangle:
:
position(Point&pt){//求点pt相对于矩形的位置
if(pt.xpos.x+width||pt.ypos.y+height)return1;//在矩形外
elseif(pt.x>pos.x&&pt.xpos.y&&pt.yelsereturn0;//在矩形边上
}
voidRectangle:
:
judge(Point&pt){//判断点pt相对于矩形的位置,给出提示
cout<<"Point:
";
pt.Show();//输出点pt的各属性值
switch(position(pt)){
case0:
cout<<"点在矩形边上"<case-1:
cout<<"点在矩形内"<case1:
cout<<"点在矩形外"<}
}
voidRectangle:
:
Show(){//输出矩形的位置、大小和面积
cout<<"rx="<cout<<"width="<cout<<"area="<
}
voidRectangle:
:
operator+=(Rectanglea){//重载运算符“+=”,两矩形的宽度和高度相加
width+=a.width;
height+=a.height;
}
intRectangle:
:
operator>(Rectanglea){//重载关系运算符“>”,比较矩形的面积
if(Area()>a.Area())return1;
elsereturn0;
}
ostream&operator<<(ostream&out,Rectangle&rg){//重载运算符<<输出矩形的各属性值
out<<"rx="<out<<"width="<returnout;
}
voidmain(){
Rectanglert1(0,0,6,8),rt2,rt3(rt1);//定义Rectangle对象
Pointp(0,0),q(9,4);//定义Point对象
cout<<"矩形rt1:
";
cout<cout<<"矩形rt2:
";
cout<cout<<"矩形rt3:
"<rt3.judge(p);//判断点p相对于矩形rt3的位置
rt3.move(q);//移动矩形rt3的位置,左下角移至点q处
p.move(8,3);//移动坐标点p的位置
cout<<"矩形rt3:
"<rt3.judge(p);//判断点p相对于矩形rt3的位置
cout<<"新的矩形rt2:
";
rt2.move(p);
rt2.set(5,5);//重置矩形rt2的宽度和高度
rt2+=rt3;//两矩形的宽度和高度相加
rt2.Show();//输出矩形rt2的位置、大小和面积
if(rt2>rt3)cout<<"矩形rt2比rt3大!
"<elsecout<<"矩形rt3比rt2大!
"<}
二、C++面向对象程序设计练习
1.定义三维空间的坐标点TPoint
2.描述三维空间的球TBall,实现其主要操作(如计算体积和表面积,输出空间坐标等)。
第2章线性表
本章实验目的:
了解线性数据结构,掌握顺序存储和链式存储的两种线性表的建立和使用方法。
一、经典算法和例题
1.顺序表的模板类
【实验目的】本例给出了较完整的顺序表的抽象数据类型定义,通过C++类模板的应用体现了数据抽象原理。
【问题描述】定义一个顺序存储的线性表数据结构,在应用程序(main函数)中建立一个整型的线性表对象,在该表中进行插入、删除、查找和输出等操作。
【数据结构】定义一个顺序存储的线性表类SeqList,数据成员包括表的存储数组,表的最大允许长度,表中最后元素下标等。
定义常用的基本操作。
【算法提示】
(1)在表示顺序表的SeqList类定义中,表元素的存储空间是数组data,采用动态内存分配方式。
表的初始化工作由构造函数实现。
(2)顺序表的基本操作以公用接口形式(类的成员函数)提供。
一般顺序表最常用的操作是输出、插入、删除、查找和求表长度等,其中数据量较大的输出操作采用运算符重载的方式来实现,以便用户能以习惯的cout<<形式输出表的全部元素。
程序2.1给出顺序表的C++类声明和部分操作的实现。