山东大学数据结构实验七:堆和搜索树

实验内容

①输入一系列不为零的正整数(最多不超过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;
}

猜你喜欢

转载自blog.csdn.net/Sunnyztg/article/details/128295089