#include<iostream>
#include<math.h>
#include<algorithm>
#include<vector>
#include<time.h>
#include<malloc.h>
using namespace std;
void heapSort(int *arr);
void heapInsert(int *arr, int index);
void heapify(int *arr, int index, int size);
void swap(int *arr, int i, int j)
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//1.要测的堆排序方法a
void heapSort(int *arr){
if(arr == NULL || _msize(arr)/sizeof(int) < 2)
return;
for (int i = 0; i < _msize(arr)/sizeof(int); i++) {
heapInsert(arr, i);
}
int size = _msize(arr)/sizeof(int);
swap(arr, 0, --size);
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, --size);
}
}
void heapInsert(int *arr, int index){
while(arr[index] > arr[(index - 1) / 2]){
swap(arr, index, (index - 1)/2);
index = (index - 1) / 2;
}
}
void heapify(int *arr, int index, int size){
int left = index * 2 + 1;
while(left < size){
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
//for test
//2.实现一个绝对正确即使复杂度不好的方法b
void comparator(int *arr){
vector<int> temp;
for(int i = 0; i < _msize(arr)/sizeof(arr); i ++)
temp.push_back(arr[i]);
sort(temp.begin(),temp.end());
for(int i = 0; i < temp.size(); i ++)
arr[i] = temp[i];
}
//for test
//3.实现一个随机样本产生器:生成容量随机和元素大小随机的数组
int *generateRandomArray(int maxSize, int maxValue){
srand((unsigned)time(NULL));
int length = (int)(rand()%maxSize+1);
int *arr = new int[length];
for(int i = 0; i < length; i ++){
arr[i] = (int)(rand()%maxValue);
}
return arr;
}
//for test
int *copyArray(int *arr){
if(arr == NULL)
return NULL;
int *res = new int[_msize(arr)/sizeof(int)];
for(int i = 0;i < _msize(arr)/sizeof(int); i ++)
res[i] = arr[i];
return res;
}
//for test
//4.实现比对的方法:判断两个数组是否相等
bool isEqual(int *arr1, int *arr2){
if((arr1 == NULL && arr2 != NULL) || (arr1 != NULL && arr1 == NULL))
return false;
if(arr1 == NULL && arr2 == NULL)
return true;
if((_msize(arr1)/sizeof(int)) != (_msize(arr2)/sizeof(int)))
return false;
for(int i = 0; i < _msize(arr1)/sizeof(int); i ++){
if(arr1[i] != arr2[i])
return false;
}
return true;
}
//for test
void printArray(int *arr){
if(arr == NULL)
return;
for(int i = 0; i < _msize(arr)/sizeof(int); i ++)
cout<<arr[i]<< " ";
cout<<endl;
}
//5.把方法a和方法b比对很多次来验证方法a是否正确
//6.如果有一个样本使得比对出错,打印样本分析是哪个方法出错
//7.当样本数量很多时比对测试依然正确,可以确定方法a已经正确
int main()
{
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
bool succeed = true;
for(int i = 0; i < testTime; i ++){
int *arr1 = generateRandomArray(maxSize, maxValue);
int *arr2 = copyArray(arr1);
heapSort(arr1);
comparator(arr2);
if(!isEqual(arr1, arr2)){
succeed = false;
break;
}
}
cout<<(succeed ? "Nice!" : "Fucking Fucked!")<<endl;
int *arr = generateRandomArray(maxSize, maxValue);
printArray(arr);//排序前打印出来
heapSort(arr);
printArray(arr);//排序后打印出来
return 0;
}
自测方法:
#include<iostream>
#include<map>
using namespace std;
//交换arr中索引分别为i和j的值
void swap(int *arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
void printArray(int *arr, int n){
for(int i = 1; i <= n; i ++){
cout<<arr[i]<<" ";
}
cout<<endl;
}
//从上往下调整节点(从索引为i的节点开始调整),用于大根堆
void adjustDown(int *arr, int i, int n){
int largest = 0;
for(int k = 2 * i; k <= n; k = k * 2){ //k为该子树的左孩子
if(k+1 <= n){ //表示i节点有右孩子
largest = (arr[k] > arr[k + 1]) ? (k) : (k + 1);//返回左右孩子较大值的下标
}
else{ //如果i节点没有右孩子
largest = k;
}
if(arr[i] >= arr[largest]) //如果当前节点小于左右孩子节点最大值
break;
else{ //如果当前节点小于左右孩子节点最大值,则交换,使该子树成为大根堆
swap(arr, i, largest);
i = largest; //修改i值,以便继续往下筛选
k = largest; //取key较大的子节点的下标
}
}
}
//建大根堆
void BuildMaxHeap(int *arr, int n){
for(int i = n / 2; i > 0; i --){
adjustDown(arr,i,n);
}
}
//堆排序:数组元素升序排序
void heapSortAscend(int *arr, int n){
BuildMaxHeap(arr, n);//初始建立大根堆
printArray(arr, n);//打印
for(int i = n; i > 1; i --){
swap(arr, i, 1);
adjustDown(arr, 1, i - 1);
printArray(arr, n);
}
}
//从上往下调整节点(从索引为i的节点开始调整),用于小根堆
void adjustDown2(int *arr, int i, int n){
int smallest = 0;
for(int k = 2 * i; k <= n; k = k * 2){ //k为该子树的左孩子
if(k+1 <= n){ //表示i节点有右孩子
smallest = (arr[k] < arr[k + 1]) ? (k) : (k + 1);//返回左右孩子较大值的下标
}
else{ //如果i节点没有右孩子
smallest = k;
}
if(arr[i] <= arr[smallest]) //如果当前节点小于左右孩子节点最大值
break;
else{ //如果当前节点小于左右孩子节点最大值,则交换,使该子树成为大根堆
swap(arr, i, smallest);
i = smallest; //修改i值,以便继续往下筛选
k = smallest; //取key较大的子节点的下标
}
}
}
//建小根堆
void BuildMinHeap(int *arr, int n){
for(int i = n / 2; i > 0; i --){
adjustDown2(arr,i,n);
}
}
//堆排序:数组元素降序排序
void heapSortdescend(int *arr, int n){
BuildMinHeap(arr, n);//初始建立小根堆
printArray(arr, n);//打印
for(int i = n; i > 1; i --){
swap(arr, i, 1);
adjustDown2(arr, 1, i - 1);
printArray(arr, n);
}
}
//for test
int main()
{
int *arr = new int[9];
//53, 17, 78, 9, 45, 65, 87, 32
for(int i = 1; i < 9; i ++){
cin>>arr[i];
}//arr[0]不存储元素
int *arr2 = new int[9];
for(int j = 1; j < 9; j ++){
arr2[j] =arr[j];//复制arr数组
}
cout<<"===============堆排序升序过程==============="<<endl;
heapSortAscend(arr, 8);
cout<<endl;
cout<<"===============堆排序降序过程==============="<<endl;
heapSortdescend(arr2, 8);
return 0;
}