0x01 实验目的
掌握堆和搜索树的基本概念,插入、删除方法。
0x02 实验内容
- 输入一系列不为零的正整数(最多不超过20个),遇到0代表输入结束(0不作为输入数据参与其中)。
- 根据上面输入的数据序列,用初始化方法创建最大堆(不要用节点依次插入的办法创建最大堆),然后输出最大堆的层次序列。
- 输出用堆排序后的排序结果。
- 根据上面输入的数据,创建二叉搜索树(关键字不允许重复,如遇重复,则不重复插入该关键字),输出二叉搜索树的前序序列、中序序列(分行输出)。
0x03 实验步骤
maxHeap的初始化操作
函数传入两个参数:一个是数组,另一个是数组中元素的个数。
- 直接将原数组释放掉,然后将新数组赋值给原数组。
- 将传入的数组元素个数赋值给类中的堆的大小。
- 从数组大小的二分之一处进行调整,最终调整为最大堆。
template<class T>
void maxHeap<T>::initialize(T theHeap[], int theSize) {
delete []heap;
heap = theHeap;
heapSize = theSize;
//copy(theHeap, theHeap + sizeof(theHeap), heap);
//memcpy(heap,theHeap,sizeof(theHeap));
for(int root = heapSize / 2; root >= 1; root--) {
//获取需要调整节点的值
T rootElement = heap[root];
//找到该节点的左子节点的索引
int child = 2 * root;
//如果子节点的索引小于等于堆的大小,就一直调整。
while(child <= heapSize) {
//找到左子节点和右子节点大的那一个节点的索引
if(child < heapSize && heap[child] < heap[child+1]) child++;
//如果根节点大于最大的那一个子节点的值,说明该根节点不需要调整,直接跳出循环。
if(rootElement >= heap[child]) break;
//否则,根节点的值为最大那个子节点的值
heap[child / 2] = heap[child];
//子节点下移一层,继续调整。
child *= 2;
}
heap[child / 2] = rootElement;
}
}
maxHeap的层次遍历
直接输出heap数组
堆排序
template<class T>
void maxHeap<T>::heapSort() {
/*
记录堆的大小,因为pop操作时会使堆的大小不断减小
而我们只排个序而已,没必要这样,后面用这个给恢复过来
*/
int temp = heapSize;
for(int i = heapSize - 1; i >= 1; i--) {
//获取最大元素
T x = top();
//删除最大元素,并重排(数组会前移一位)
pop();
//最大元素放在最后前移空出来的那一位
heap[i+1] = x;
}
//恢复堆的大小
heapSize = temp;
//deactivateArray();
}
创建二叉搜索树
说明: 创建二叉搜索树,是按照我们输入的数组顺序来的,不是排序后的数组。按照数组顺序依次插入即可。
- 一般的节点类
class Node {
public:
Node() {
leftChild = NULL;
rightChild = NULL;
key = 0;
}
Node(int element) {
key = element;
leftChild = NULL;
rightChild = NULL;
}
Node *leftChild;
Node *rightChild;
int key;
};
- bsTree类
class bsTree {
public:
bsTree() {
root = NULL;
};
void insert(int);
void preOrder(Node*);
void inOrder(Node*);
Node *root;
};
- 插入操作
//插入操作,很简单,就是双指针+比较大小
void bsTree::insert(int element) {
Node *n = new Node(element);
if(root == NULL) root = n;
else {
Node *current = root;
Node *pre = root;
while(current) {
pre = current;
if(current->key > element) {
current = current->leftChild;
} else current = current->rightChild;
}
if(pre->key > element) pre->leftChild = n;
else pre->rightChild = n;
//只是将指针移到了n,但没改变指向。
//current = n;
}
}
二叉搜索树的前序遍历和中序遍历
- 中序遍历和堆排序后的结果差不多,
可以直接去重输出。 - 遍历本身并不难,感觉比较复杂的是逗号的输出,可看完整代码理解,在此不作赘述。
void bsTree::inOrder(Node *node) {
if(node == NULL) return;
if(node->leftChild == NULL && flag == false) {
flag = true;
inOrder(node->leftChild);
cout<<node->key;
inOrder(node->rightChild);
} else {
inOrder(node->leftChild);
cout<<","<<node->key;
inOrder(node->rightChild);
}
}
void bsTree::preOrder(Node *node) {
if(node == NULL) return;
if(root == node) {
cout<<node->key;
preOrder(node->leftChild);
preOrder(node->rightChild);
} else {
cout<<","<<node->key;
preOrder(node->leftChild);
preOrder(node->rightChild);
}
}
0x04 最终代码
#include<bits/stdc++.h>
using namespace std;
const int M = 100000;
int arr[M];
int brr[M];
bool crr[M];
bool flag = false;
class Node {
public:
Node() {
leftChild = NULL;
rightChild = NULL;
key = 0;
}
Node(int element) {
key = element;
leftChild = NULL;
rightChild = NULL;
}
Node *leftChild;
Node *rightChild;
int key;
};
class bsTree {
public:
bsTree() {
root = NULL;
};
void insert(int);
void preOrder(Node*);
void inOrder(Node*);
Node *root;
};
void bsTree::inOrder(Node *node) {
if(node == NULL) return;
if(node->leftChild == NULL && flag == false) {
flag = true;
inOrder(node->leftChild);
cout<<node->key;
inOrder(node->rightChild);
} else {
inOrder(node->leftChild);
cout<<","<<node->key;
inOrder(node->rightChild);
}
}
void bsTree::preOrder(Node *node) {
if(node == NULL) return;
if(root == node) {
cout<<node->key;
preOrder(node->leftChild);
preOrder(node->rightChild);
} else {
cout<<","<<node->key;
preOrder(node->leftChild);
preOrder(node->rightChild);
}
}
//插入操作
void bsTree::insert(int element) {
Node *n = new Node(element);
if(root == NULL) root = n;
else {
Node *current = root;
Node *pre = root;
while(current) {
pre = current;
if(current->key > element) {
current = current->leftChild;
} else current = current->rightChild;
}
if(pre->key > element) pre->leftChild = n;
else pre->rightChild = n;
//只是将指针移到了n,但没改变指向。
//current = n;
}
}
template <class T>
class maxHeap {
public:
maxHeap() {
heapSize = 0;
arrayLength = 0;
heap = new T[arrayLength];
//flag = false;
};
void initialize(T theHeap[], int size);
void levelOutput();
void heapSort();
T top();
void pop();
//void deactivateArray();
private:
int heapSize;
int arrayLength;
T* heap;
//bool flag;
};
//template<class T>
//void maxHeap<T>::deactivateArray(){
// flag = true;
//}
template<class T>
void maxHeap<T>::pop() {
if(heapSize == 0) return;
//if(flag == false)
//删除最大元素
heap[1].~T();
T last = heap[heapSize--];
int current = 1;
int child = 2;
//与初始化有异曲同工之妙
while(child <= heapSize) {
//找两个孩子的大者
if(child < heapSize && heap[child] < heap[child+1]) child++;
if(last >= heap[child]) break;
heap[current] = heap[child];
current = child;
child = child * 2;
}
heap[current] = last;
//flag = false;
}
template<class T>
T maxHeap<T>::top() {
return heap[1];
}
template<class T>
void maxHeap<T>::heapSort() {
int temp = heapSize;
for(int i = heapSize - 1; i >= 1; i--) {
T x = top();
pop();
heap[i+1] = x;
}
heapSize = temp;
//deactivateArray();
}
template<class T>
void maxHeap<T>::initialize(T theHeap[], int theSize) {
delete []heap;
heap = theHeap;
heapSize = theSize;
//copy(theHeap, theHeap + sizeof(theHeap), heap);
//memcpy(heap,theHeap,sizeof(theHeap));
for(int root = heapSize / 2; root >= 1; root--) {
T rootElement = heap[root];
int child = 2 * root;
while(child <= heapSize) {
if(child < heapSize && heap[child] < heap[child+1]) child++;
if(rootElement >= heap[child]) break;
heap[child / 2] = heap[child];
child *= 2;
}
heap[child / 2] = rootElement;
}
}
template<class T>
void maxHeap<T>::levelOutput() {
for(int i = 1; i <= heapSize; i++) {
if(i == 1) cout<<heap[i];
else cout<<","<<heap[i];
}
cout<<endl;
}
int main() {
cout<<"Input"<<endl;
int index = 0;
int temp;
do {
index++;
cin>>temp;
arr[index] = temp;
brr[index] = temp;
} while(temp != 0);
maxHeap<int> heap;
heap.initialize(arr, index - 1);
cout<<"Output"<<endl;
heap.levelOutput();
heap.heapSort();
heap.levelOutput();
bsTree bstree;
for(int i = 1; i < index; i++) {
if(crr[brr[i]] == false) {
crr[brr[i]] = true;
bstree.insert(brr[i]);
}
}
bstree.preOrder(bstree.root);
cout<<endl;
bstree.inOrder(bstree.root);
cout<<endl;
cout<<"End"<<endl;
return 0;
}