堆的构建插入和删除.docx
《堆的构建插入和删除.docx》由会员分享,可在线阅读,更多相关《堆的构建插入和删除.docx(11页珍藏版)》请在冰豆网上搜索。
堆的构建插入和删除
成绩:
山东大学
《C++程序设计》实验报告
实验46:
层次逻辑
学号:
201200301058
姓名:
高强
实验时间:
2014年3月7日星期五
《C++程序设计》实验报告
一、实验名称
层次逻辑:
堆的构建、插入和删除
二、实验目的
1.熟悉栈这种特殊线性结构的特性;
2.熟练并掌握栈在顺序存储结构和链表存储结构下的基本运算;
3.熟练掌握堆的构建插入和删除。
4.尽可能地用可视化的形式表现出来。
三、实验平台
Windows7、VisualStudio6.0
四、实验内容
1.首先要实现树型的输出,这个是我想地最多的。
我采用的是递归调用的方法。
通过字符串的拼接将其输出为一种树型。
if(left<=treesize){
//这个条件判断的是怎么输出树叶
if(right>treesize){
cout<realtree(right,emp1);//递归调用
}
else{
//这俩判断的是怎么输出左右子树
cout<realtree(left,emp1);//递归调用
cout<realtree(right,emp2);//递归调用
其中的特殊符号用的是表格线,感觉上比较像一棵树。
2.另外的一个就是输出函数:
voidprinttree(void){
//这个是输出树型的方法
if(treesize!
=0){
//树的大小不为零才可输出
charemp[EMP_SIZE]="";
cout<<""<realtree(1,emp);//这个是调用上面的函数将除根以外的元素输出出来
cout<}
else{
//树为空则输出“树为空”
cout<<"树为空"<}
}
3.在一个就是堆的基本操作方法,包括构建、插入和删除。
因为书上的模板类完全不会调用,所以索性自己写了几个方法。
调整最大堆的方法,就是将父节点和孩子进行比较,找到最大的然后移到父节点,形成最大堆:
voidHeapAdjust(intk,intm){
intvalue=tree[k];
while(2*k<=m){
ints=2*k;
if(2*k+1<=m&&tree[2*k+1]>tree[2*k]){
s=2*k+1;
}
if(value>=tree[s]){
//已经是最大堆则直接跳出条件
break;
}
else{
//否则就交换最大节点与父节点
tree[k]=tree[s];
k=s;
}
}
tree[k]=value;
}
最大堆的插入和输出函数:
voidheapdelete(void){
for(intj=5;j>=1;j--){
//这个循环将最大堆初始化
HeapAdjust(j,10);
}
cout<<"堆的初始化:
"<printtree();
//把删除的元素赋给新建的值,然后交换原先的值和最后一个元素的值,再删除最后一个元素。
cout<<"请输入要删除的元素序号:
"<intm;
cin>>m;
intx=tree[m];
tree[m]=tree[treesize];
treesize--;
for(inth=treesize/2;h>=1;h--){
HeapAdjust(h,treesize);
}
cout<<"删除"<"<printtree();
//将输入的数插入到根节点,然后重排。
感觉这个方法好浪费时间
cout<<"请输入要插入的元素:
"<cin>>m;
treesize++;
tree[treesize]=tree[1];
tree[1]=m;
for(intw=treesize/2;w>=1;w--){
HeapAdjust(w,treesize);
}
cout<<"添加"<"<printtree();
}
五、代码分析
#include
#include
#include
#include
#defineMAX_SIZE=10//初始化数组的大小
#defineEMP_SIZE100//设置递归调用时的字符串的数量
inttree[10]={-1,11,22,33,44,55,66,77,88,99};//初始化树,当然也可以用循环或者递归输入,这里求简
inttreesize=9;//设置树的的大小,方法调用里面可能会改变这个值
//┗━┃┣
voidrealtree(intk,charemp[EMP_SIZE]){
//这个是我自己写的形式化输出树的形式的代码,花了很长时间,可能不是很完善
intleft=2*k;//左子树
intright=2*k+1;//右子树
charemp1[EMP_SIZE];
charemp2[EMP_SIZE];
//设置两个字符串,以便以后递归调用
strcpy(emp1,emp);//将emp的字符赋值给emp1,是为了递归调用的时候覆盖先前的字符串
strcpy(emp2,emp);
strcat(emp1,"┃");//strcpy方法是将后边的字符串连接到的前面的字符串后面
strcat(emp2,"");
if(left<=treesize){
//这个条件判断的是怎么输出树叶
if(right>treesize){
cout<realtree(right,emp1);//递归调用
}
else{
//这俩判断的是怎么输出左右子树
cout<realtree(left,emp1);//递归调用
cout<realtree(right,emp2);//递归调用
}
}
}
////////////////////////////////////////////////////////////////
voidprinttree(void){
//这个是输出树型的方法
if(treesize!
=0){
//树的大小不为零才可输出
charemp[EMP_SIZE]="";
cout<<""<realtree(1,emp);//这个是调用上面的函数将除根以外的元素输出出来
cout<}
else{
//树为空则输出“树为空”
cout<<"树为空"<}
}
////////////////////////////////////////////////////////////
voidHeapAdjust(intk,intm){
//这个是调整最大堆的方法,就是将父节点和孩子进行比较,找到最大的然后移到父节点,形成最大堆
intvalue=tree[k];
while(2*k<=m){
ints=2*k;
if(2*k+1<=m&&tree[2*k+1]>tree[2*k]){
s=2*k+1;
}
if(value>=tree[s]){
//已经是最大堆则直接跳出条件
break;
}
else{
//否则就交换最大节点与父节点
tree[k]=tree[s];
k=s;
}
}
tree[k]=value;
}
////////////////////////////////////////////////////////////
voidheapdelete(void){
//这个是最大堆的插入和输出函数
for(intj=5;j>=1;j--){
//这个循环将最大堆初始化
HeapAdjust(j,10);
}
cout<<"堆的初始化:
"<printtree();
//把删除的元素赋给新建的值,然后交换原先的值和最后一个元素的值,再删除最后一个元素。
cout<<"请输入要删除的元素序号:
"<intm;
cin>>m;
intx=tree[m];
tree[m]=tree[treesize];
treesize--;
for(inth=treesize/2;h>=1;h--){
HeapAdjust(h,treesize);
}
cout<<"删除"<"<printtree();
//将输入的数插入到根节点,然后重排。
感觉这个方法好浪费时间
cout<<"请输入要插入的元素:
"<cin>>m;
treesize++;
tree[treesize]=tree[1];
tree[1]=m;
for(intw=treesize/2;w>=1;w--){
HeapAdjust(w,treesize);
}
cout<<"添加"<"<printtree();
}
////////////////////////////////////////////////////////////////
intmain(){
//主函数,我们要呈现树型,要实现堆的插入和删除功能
cout<<"原始数表:
"<inttreesize=10;
inttree[]={-999,11,22,33,44,55,66,77,88,99};
printtree();
heapdelete();
return0;
}
六、实验截图
七、实验总结
通过这次实验,提高的是C++的半程水平,原先数据结构课程怎加的基本上都是理论知识,现在才真正去自己紫萼一下代码。
感受颇多,淡然代码还有很多不足的地方,我会加倍努力。