实验内容
①输入一系列不为零的正整数(最多不超过20个),遇到0代表输入结束(不包含0)。
②根据上面输入的数据序列,用初始化方法创建最大堆(不要用节点依次插入的办法创建最大堆),然后输出最大堆的层次序列。
③输出用堆排序后的排序结果。
④根据上面输入的数据,创建二叉搜索树(关键字不允许重复,如遇重复,则不重复插入该关键字),输出二叉搜索树的前序序列、中序序列(分行输出)。
实验步骤
①首先复习最大堆有关知识(非插入方式的初始化、删除、堆排序等)和二叉搜索树有关知识(构造、遍历等),在草稿纸上模拟程序过程,有了更深入的理解。
②按照题目要求,先编写最大堆的类MaxHeap,内含数组、当前元素个数和最大元素个数等值,线性表数组用于存储堆,按照1、2、...编号存储,对于节点i,2i和2i+1是子节点。然后编写堆的初始方法,需要传入初始数组。从一个无序序列初始化为一个堆的过程就是一个反复“筛选”的过程。由完全二叉树的性质可以知,一个有n个节点的完全二叉树的最后一个非叶节点是节点[n/2],堆的初始化过程就从这个[n/2]节点开始,一直遍历到1号节点,对于每个遍历到的节点,都要和父节点比较,如果比父节点还大,就向上层交换,一直到根节点,这里编程的时候需要注意的细节是选定子节点中的最大值,然后还要判断是否超出最大数据个数。
③堆排序,宏观上看原理十分简单,就是一次次取出最大的元素,把最大的元素逆序保存在结果数组中,然后把这个元素从堆中删除即可。从堆中删除元素的步骤为,去掉根节点,把满二叉树最后一个元素放到根节点上,然后按照它的大小锁定合适的位置(与子节点比,如果小于子节点,就和子节点中最大的交换,否则就放到原位置)。
④构造二叉搜索树。方便起见,我只写了BSTreeNode类,存放节点元素,包含
Data left right三个数据域。初始化搜索树,我是通过不断向根节点中插入元素的形式处理的。设计这部分算法时,要注意保留当前遍历节点的父节点,然后如果要插入的数据比当前节点数据小,就移动到左节点,否则就移动到右节点,注意不能插入重复元素,遇到重复的就break,这里又加了一个bool变量,如果break的话,在此前要把其设成false,只有在true的情况下会创建新节点并在保留的父节点下按照元素大小规则插入。
⑤前序和中序遍历,依然按照上个实验的方式递归构造。需要注意,必须判断当前指针不为空的情况下运行,不然会出错。
调整一些bug和优化流程后,程序成功运行:
本次实验主要代码:
#include<bits/stdc++.h>
using namespace std;
int countt=1;
int dataa=0;
int repeat = 0;
class MaxHeap {
public :
MaxHeap(int MaxHeapSize = 10);
~MaxHeap() {delete [] heap;}
int Size() const {return CurrentSize;}
int Max() {
return heap[1];}
MaxHeap& Insert (const int& x);
MaxHeap& DeleteMax (int& x);
void Initialize (int a[], int size, int ArraySize);
int CurrentSize, MaxSize;
int *heap; // 元素数组
} ;
MaxHeap::MaxHeap(int MaxHeapSize)
{ // 构造函数
MaxSize = MaxHeapSize;
heap = new int[MaxSize+1];
CurrentSize = 0;
}
MaxHeap& MaxHeap::DeleteMax(int& x)
{ //将最大元素放入x,并从堆中删除最大元素。首先检查堆是否为空
x=heap[1]; //根为最大元素。 删除根后重构堆
int y=heap[CurrentSize--]; //y最后元素。从根开始为y寻合适位置
int i=1, ci=2; //i:堆的当前节点;ci:i的孩子
while (ci<=CurrentSize) {
if(ci<CurrentSize && heap[ci]<heap[ci+1]) ci++; //heap[ci]应该是i较大的孩子
if (y>=heap[ci]) break; //能把y放入heap[i]吗?能则结束
heap[i]=heap[ci]; //不能
i=ci; ci*=2; }//while
heap[i]=y;
return *this;
}
void MaxHeap::Initialize(int a[],int size,int ArraySize){
delete[] heap;
heap = a;
CurrentSize = size;
MaxSize = ArraySize;
for(int i=CurrentSize/2;i>=1;i--){
int y = heap[i];
int c = 2*i;
while(c <= CurrentSize){
if(c<CurrentSize && heap[c]<heap[c+1])c++;
if(y >= heap[c])break;
heap[c/2] = heap[c];
c*=2;
}
heap[c/2] = y;
}
}
void HeapSort(MaxHeap H, int a[],int n)
{ // 利用堆排序算法对a[1:n] 进行排序
// 从最大堆中逐个抽取元素
int x;
for (int i = n-1; i >= 1; i--) {
H.DeleteMax(x) ; //返回x
a[i+1] = x;} //自后向前安置
}
class BSTreeNode {
public:
int data;
BSTreeNode *left;
BSTreeNode *right;
};
void BSInsert(BSTreeNode *root,int indata){
BSTreeNode *pp;
BSTreeNode *p=root;
bool flag = true;
while(p!=NULL){
pp = p;
if(indata < p->data){
p = p->left;
}
else if(indata > p->data)
p = p->right;
else{
flag = false;
repeat++;
break;//重复
}
}
if(flag){
BSTreeNode *temp=new BSTreeNode();
temp->data = indata;
//确保树非空
if(indata<pp->data)
pp->left = temp;
else pp->right = temp;
}
}
void pre(BSTreeNode *root,int dataa){
if(root!=NULL){
if(countt != dataa) {
cout<<root->data<<",";
countt++;
}
else
cout<<root->data<<endl;
pre(root->left,dataa);
pre(root->right,dataa);}
}
void mid(BSTreeNode *root,int dataa){
if(root!=NULL){
mid(root->left,dataa);
if(countt != dataa) {
cout<<root->data<<",";
countt++;}
else
cout<<root->data<<endl;
mid(root->right,dataa);}
}
int main(){
cout<<"Input"<<endl;
int input;
int h[20];
int hh[20];
int num=0;
while(cin>>input&&input!=0){
h[++num] = input;
hh[num] = h[num];
}
MaxHeap H(1);
H.Initialize(h,num,num);
cout<<"Output"<<endl;
for(int i=1;i<num;i++){
cout<<H.heap[i]<<",";
}
cout<<H.heap[num]<<endl;
HeapSort(H,h,num);
for(int i=1;i<num;i++){
cout<<h[i]<<",";
}
cout<<h[num]<<endl;
BSTreeNode * root=new BSTreeNode();
root->data = hh[1];
if(num>1)
for(int i=2;i<=num;i++){
BSInsert(root,hh[i]);
}
dataa =num-repeat;//控制输出
pre(root,dataa);
countt=1;
mid(root,dataa);
cout<<"End"<<endl;
return 0;
}