c++各种排序实验以及学生信息的修改.docx
《c++各种排序实验以及学生信息的修改.docx》由会员分享,可在线阅读,更多相关《c++各种排序实验以及学生信息的修改.docx(24页珍藏版)》请在冰点文库上搜索。
c++各种排序实验以及学生信息的修改
哈尔滨工业大学(威海)软件学院
C程序设计实验报告
编号:
姓名
孟令鑫
院系
软件学院
学号
131110412
任课教师
丁建睿
指导教师
实验地点
研究院中507-508
实验时间
2014年4月5日
实验名称
类的深入剖析
同组人
无
预习报告(对实验主要内容的认识)
得分
熟悉函数重载和函数模板
灵活运用数组处理数据信息
了解C++类模板vector
深入了解c++指针与引用的区别
深入剖析C++中的内存分配方式
了解C++中的构造函数、析构函数
区别默认构造函数、带参构造函数和拷贝构造函数
初步了解static关键字
学习各种排序方法
了解析构函数析构顺序
实验内容(问题,思路,程序,结果)
得分
实验一——学生信息修改
1、设计思路:
通过实验中已经给定的.h头文件可知,在这个事例中,需要在类中定义的变量以及函数和函数参数,这里要格外注意几个构造函数的定义,以及public函数设置和private的变量设置以保证除了类中的函数,其他函数和命令不能对变量进行修改。
这里格外注意对student的同名构造函数的定义,以及函数参数的设置
问题实现函数的接口设置对用户隐形。
在student.cpp文件中,进行函数
的实现,对各个函数进行类外的定义,这里要注意在类外定义函数的时
候要使用“:
:
”二元作用域运算符。
Set,get函数主要通过赋值进行在
main函数中进行相关函数的调用实现函数的测试时候,要注意静态对象
以及全局对象的定义。
2、代码设置:
《main函数》
#include
#include"student.h"
usingnamespacestd;
voidcreat();//声明creat函数
Studentfirst("李勇","男",21);//使用带参构造函数定义全局对象
intmain()
{
cout<<"globalbeforemainby~带参构造函数"<first.printStudentInfo();//调用对象first打印函数
cout<<"******MAINFUCTION:
EXECUTIONBEGINS*******"<Studentsecond("刘斯璇","男",18);//使用带参构造函数定义对象,
cout<<"localautomaticinmainby~带参构造函数"<second.printStudentInfo();
Studentthird(second);//使用拷贝构造函数定义对象
cout<<"localautomaticinmainby~拷贝造函数"<third.printStudentInfo();
Student*forth=newStudent("王岳","男",18);//new申请动态内存
cout<<"localautomaticinmainby~new建立的动态的对象"<(*forth).printStudentInfo();
deleteforth;//释放内存
cout<<"******CREATFUCTION:
EXECUTIONBEGINS*******"<creat();//调用creat函数
//creat
(2);
Studentseven;
cout<<"localautomaticinmainby~默认构造函数"<seven.printStudentInfo();
staticStudenteight;//定义静态对象
cout<<"localstaticinmainby~默认构造函数"<eight.printStudentInfo();
return0;
}
voidcreat()
{
//if(select==1)
{
Studentfifth("刘成达","男",19);
cout<<"localautomaticincreatby~带参造函数"<fifth.printStudentInfo();
//}
//if(select==1)
//{
staticStudentsixth("山昌","男",18);
cout<<"localstaticincreatby~带参造函数"<sixth.printStudentInfo();
}
}
《student。
Cpp文件》
#include
#include"student.h"
usingnamespacestd;
intStudent:
:
count=0;
//intflag=0;
intconstArraysize=10;
intnum=0;
//intNUM=0;
intserial[Arraysize];//定义一个数组,保存produceID的编号是否使用
//定义带参构造函数
Student:
:
Student(stringName,stringSex,intAge)
{
count++;//调用构造函数时,计数器加一
setName(Name);
setSex(Sex);
setAge(Age);
num=produceID();//用num保存所产生的ID
serial[num]=1;//调用构造函数时,将数组赋值为1,表示已经使用该位置
setStudentID(num);
cout<<"Object"<:
getCount()<//printStudentInfo();
}
//定义默认构造函数
Student:
:
Student()
{
count++;//调用构造函数时,计数器加一
name="默认";
sex="女";
age=18;
num=produceID();
serial[num]=1;//调用构造函数时,将数组赋值为1,表示已经使用该位置
setStudentID(num);
cout<<"Object"<:
getCount()<//printStudentInfo();
}
//定义拷贝构造函数
Student:
:
Student(Student&temp)
{
count++;//调用构造函数时,计数器加一
name=temp.name;
sex=temp.sex;
age=temp.age;
num=produceID();
serial[num]=1;//调用构造函数时,将数组赋值为1,表示已经使用该位置
setStudentID(num);
cout<<"Object"<:
getCount()<//printStudentInfo();
}
Student:
:
~Student()
{
//flag=1;
count--;//调用析构函数时,计数器减一
num=getStudentID();
serial[num]=0;
cout<<"Object"<:
getCount()<}
voidStudent:
:
setName(stringName)//fuctiongtosetstudentname
{
name=Name;
}
voidStudent:
:
setSex(stringSex)//fuctiontosetstudentsex
{
sex=Sex;
}
voidStudent:
:
setAge(intAge)//fuctiontosetstudentage
{
age=Age;
}
stringStudent:
:
getName()//fuctiontogetstudentName
{
returnname;
}
stringStudent:
:
getSex()//fuctiontogetstudentsex
{
returnsex;
}
intStudent:
:
getAge()//fuctiontogetstudentage
{
returnage;
}
//产生学生序号的函数
intStudent:
:
produceID()
{
staticintID=1;
inti;
for(i=1;i<=Arraysize;i++)//遍历数组,当数组中的数为1时表示该位置已经使用,紧接着做++操作,当数组中的数为0时,表示该位置没有使用。
则返回该位置。
{
if(serial[i]==0)//当该ID数组可以使用的时候,赋值为一,表示已经使用,下次无法使用
{
serial[i]=1;
break;//当找到为0的位置,跳出循环不再寻找。
优化函数,减少循环次数
}
}
ID=i;
returnID;//返回该位置
}
voidStudent:
:
printStudentInfo()//打印学生信息
{
cout<<"******学生信息******"<"<"<"<}
intStudent:
:
getCount()
{
returncount;
}
voidStudent:
:
setStudentID(intStudentID)
{
studentID=StudentID;
}
intStudent:
:
getStudentID()//得到学生的学号
{
returnstudentID;
}
《头文件》
#ifndefSTUDENT_H_INCLUDED
#defineSTUDENT_H_INCLUDED
#include
//#include
#include
usingnamespacestd;
classStudent
{
public:
Student();//Student的默认构造函数
Student(Student&);//Student的拷贝构造函数
Student(string,string,int);//构造函数有3个参数分别对应姓名性别年龄
~Student();
voidsetStudentID(int);//对象编号
voidsetName(string);
voidsetSex(string);
voidsetAge(int);
intgetStudentID();
stringgetName();
stringgetSex();
intgetAge();
intproduceID();//产生编号
voidprintStudentInfo();//打印学生信息
//voidmodifyStudentInfo();//修改学生信息
staticintgetCount();//获取当前Student对象数
private:
staticintcount;//统计Student对象的个数
intstudentID;//Student对象的编号
intage;
stringname;
stringsex;
};
#endif//STUDENT_H_INCLUDED
3、遇到问题和解决方法:
(1)将cout语句写在了main函数的外面。
导致程序报错不能运行。
经查询,除定义全局变量和声明、定义函数之外单独的一条命令不能写在主函数之外
(2)new分配动态内存时出错,将new后的类名写作了对象名。
(3)ID可以重复使用不知道如何编写。
经过查询以及思考,采用了数组的方式,定义为全局变量则自动初始化全部为0.如果该位置(数组下标加一)已经调用构造函数被使用,则该位置的数组中的数被置一,如果调用了析构函数则该位置被置0代表没有被使用,则还可以使用。
然后返回该位置即可。
(3)在produceID函数中,出现了只要呗析构函数调用了之后ID就不再变化的情况,经反复调试发现,当将析构函数调用的置0部分写在该函数中,调用析构函数的时候并没有使用该函数,则导致下次调用构造函数的时候才会调用。
改为在析构函数中直接置0。
实验二——排序问题。
1、设计思路:
通过查阅各种排序原理,
(1)冒泡排序算法的运作如下:
(从后往前)
比较相邻的元素。
如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。
在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
(2)快速排序法:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
(3)选择排序法:
对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。
然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。
(4)希尔排序法:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。
所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插入排序;然后,取第二个增量d2(5)归并排序法:
第一步:
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列第二步:
设定两个指针,最初位置分别为两个已经排序序列的起始位置第三步:
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置重复步骤3直到某一指针超出序列尾将另一序列剩下的所有元素直接复制到合并序列尾(6)堆排序:
将数组构造为初始堆;再将当前无序区的堆顶记录(最大值)和该区间的最后一个记录交换,然后将新的无序区调整为堆。
Main代码整合:
利用dowhile循环,建立选择菜单,用户可以反复选择操作或者退出。
利用whlie循环以及cin.clear();cin.sync();和cin函数的返回值来判断用户输入是否符合输入要求,并进行容错处理。
之后利用ifelseifeles条件语句进行用户的选择操作。
这里在各选择语句执行结束之后统一编
totaltime=(double)(finish-start)/CLOCKS_PER_SEC
for(inti=0;i<30000;i++)
{
cout<
}
cout<<"\n此排序运行时间为"<"<时间计算语句和输出语句,减少了代码的复杂性
再进行类的定义以及函数和类的封装,这里在.h文件中将intachieveRandomFromFile()改为int*achieveRandomFromFile()。
将返回值类型改为指针,返回数组的地址。
2、代码设置:
《主函数》
#include
#include"datasort.h"
#include"RandomNumAndFileOperate.h"
#include
#include
usingnamespacestd;
intmain()
{
intchoiceOperate;
intrond[30000];//定义数组存放数据
produceRandomNumber();
int*p=achieveRandomFromFile();//定义指针保存返回值
cout<<"\t\t30000个随机数已经生成!
"<cout<<"\t\t请选择使用的排序方式:
"<do{//使用dowhile循环方便用户重复使用
clock_tstart,finish;//操作开始和结束的时间
doubletotaltime;
//对错误数输入的容错处理
while(cout<<"1、冒泡排序\t2、快速排序\t3、希尔排序\t4、选择排序\n5、归并排序\t6、堆排序\t0、退出程序"<>choiceOperate,!
(choiceOperate==1||choiceOperate==2||choiceOperate==3||choiceOperate==4||choiceOperate==5||choiceOperate==6||choiceOperate==0)||cin.fail())
{
cout<<"输入错误,请重新输入"<cin.clear();//清楚cin输入的字符
cin.sync();
}
if(choiceOperate==1)//冒泡
{
start=clock();
bubbleSorting(p,30000);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;//计算时间
}
elseif(choiceOperate==2)//快速
{
start=clock();
quickSort(p,0,29999);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
}
elseif(choiceOperate==3)//希尔
{
start=clock();
shellSorting(p,30000);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
}
elseif(choiceOperate==4)//选择
{
start=clock();
selection(p,30000);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
}
elseif(choiceOperate==5)//归并
{
start=clock();
MergeSort(p,rond,0,29999);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
}
elseif(choiceOperate==6)//堆
{
start=clock();
Heap_sort(p,30000);
finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
}
elseif(choiceOperate==0)
{
return0;
}
else
{
cout<<"输入错误,请重新输入"<}
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;//计算时间
for(inti=0;i<30000;i++)
{
cout<
}
cout<<"\n此排序运行时间为"<"<}while(choiceOperate!
=0);
return0;
}
《datasort。
cpp》
#include
#include"datasort.h"
usingnamespacestd;
//选择排序
voidselection(inta[],intn)
{
inti,j,k,temp;
for(i=0;i{
k=i;
for(j=i+1;j{
if(a[j]{
k=j;
}
}
if(k!
=i)
{
temp=a[k];
a[k]=a[i];
a[i]=temp;
}
}
}
//冒泡排序
voidbubbleSorting(inta[],intn)
{
inti,j,t;
for(i=1;i{
for(j=0;j{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
//快速排序
intpartition(inta[],intp,intr)
{
intx=a[r];
intmiddle=p;
for(intj=p;j{
if(a[j]{
if(j!
=middle)
{
i