void Swap(int &x,int &y){
int temp = x;
x = y;
y = temp;
}
引用调用,不然数组的两个元素并未真正的交换值。
数组堆化只是符合二叉堆的要求而已,只是根是最小的而已,堆排序就是
第一次 把这个最小的数与数组最后一个数交换,然后下次把剩下的n-1个数从新弄成最小堆,此时根元素是第二个最小的数,再把根元素跟到第二个数交换,直到把所有的数交换完为止,这样最小的数就到了最后面的位置,整个数组是降序排列。如果每次打印根元素连续打印的数可以看出是从小到大排列的。
#include<iostream>
#include<time.h>
#define random(x) (rand()%x)
using namespace std;
void Swap(int &x,int &y){
int temp = x;
x = y;
y = temp;
}
// 新加入i结点 其父结点为(i - 1) / 2
void MinHeapFixup(int a[], int i)
{
int j, temp;
temp = a[i];
j = (i - 1) / 2; //父结点
while (j >= 0 && i != 0)
{
if (a[j] <= temp)
break;
a[i] = a[j]; //把较大的子结点往下移动,替换它的子结点
i = j;
j = (i - 1) / 2;
}
a[i] = temp;
}
//在最小堆中加入新的数据nNum
void MinHeapAddNumber(int a[], int n, int nNum)
{
a[n] = nNum;
MinHeapFixup(a, n);
}
// 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void MinHeapFixdown(int a[], int i, int n)
{
int j, temp;
temp = a[i];
j = 2 * i + 1; //数组下标第一个位置是零,j是做孩子,j+1 是右孩子
while (j < n) //循环结束的条件是 j<n
{
if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
j++; //现在j是最小孩子的坐标,如果左孩子比较小那么j还是j,否则j+1
if (a[j] >= temp) //如果最小的孩子节点都比父节点大,那么就不用替换了
break;
a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点
i = j; //实现循环操作,现在把当前最小孩子节点当成父节点继续循环
j = 2 * i + 1;
}
a[i] = temp; //最后把父节点给那个最终父节点落在的位置。
}
//在最小堆中删除数
void MinHeapDeleteNumber(int a[], int n)
{
Swap(a[0], a[n - 1]);
MinHeapFixdown(a, 0, n - 1);
}
//建立最小堆
void MakeMinHeap(int a[], int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
MinHeapFixdown(a, i, n);
}
void MinheapsortTodescendarray(int a[], int n)
{
for (int i = n - 1; i >= 1; i--)
{
cout<<"根节点为:"<<a[0]<<endl;
Swap(a[i], a[0]);
MinHeapFixdown(a, 0, i);
}
//cout<<"根节点为:"<<a[0]<<endl;
}
void printArray(int a[],int n){
for(int i =0;i<n;i++){
cout<< a[i]<<" ";
}
}
int main(){
time_t t;
int a[10]={0};
srand((unsigned) time(&t));
for(int i =0;i<=9;i++){
a[i]= random(100);
}
//int a[10]={6,2,3,8,4,1,7,9,0,5};
cout<<"原数组为:"<<endl;
printArray(a,10);
MakeMinHeap(a,10);
cout<<endl<<"数组堆化后为:"<<endl;
printArray(a,10);
MinheapsortTodescendarray(a,10);
cout<<endl<<"排序后的数组为:"<<endl;
printArray(a,10);
system("pause");
return 0;
}