下面是我写的程序
这个程序不明白的是:双亲结点与孩子结点交换了数据,如果孩子结点并不是最大堆,也需要把孩子结点调成最大堆的情况,这个程序是怎么做的,我写这个程序时没有专门操作,但却对了,我并不知道是怎么做的
#include <stdio.h>
typedef int KeyType;
struct DataType
{
KeyType key;
};
/*创建最大堆*/
void CreatHeap(struct DataType a[],int n) //把数据 a[] 调成最大堆(从下向上), n 为数组中元素个数
{
int i,j;
int h = 0; // h 为根结点下标
struct DataType temp; //定义一个临时变量
//求第一个非叶结点的下标,结果保存在 j 中
i = h;
while(1)
{
if(2 * i + 1 >= n -1) //最后一个非叶结点,只有左子树
{
j = i;
break;
}
else if(2 * i + 2 >= n -1) //最后一个非叶结点,有左子树,和右子树
{
j = i;
break;
}
i ++;
}
//交换数据,生成最大堆
if(2 * j + 1 == n-1) //最后一个非叶结点,只有左子树的情况
{
if(a[j].key < a[2*j+1].key) //最后一个非叶结点,只有左子树
{
temp = a[j];
a[j] = a[2*j+1];
a[2*j+1] = temp;
}
j = j -1; //其它非叶结点,既有左子树又有右子树
for( ; j >= h; j--)
{
//双亲结点与最大孩子结点交换数据
if(a[j].key < a[2*j+1].key || a[j].key < a[2*j+2].key)
{
if(a[2*j+1].key < a[2*j+2].key)
{
temp = a[j];
a[j] = a[2*j+2];
a[2*j+2] = temp;
}
else
{
temp = a[j];
a[j] = a[2*j+1];
a[2*j+1] = temp;
}
}
}
}
else if(2 * j + 2 == n-1) //最后一个非叶结点,有左子树,也有右子树的情况
{
for( ; j >= h; j--)
{
//双亲结点与最大孩子结点交换数据
if(a[j].key < a[2*j+1].key || a[j].key < a[2*j+2].key)
{
if(a[2*j+1].key < a[2*j+2].key)
{
temp = a[j];
a[j] = a[2*j+2];
a[2*j+2] = temp;
}
else
{
temp = a[j];
a[j] = a[2*j+1];
a[2*j+1] = temp;
}
}
}
}
}
/*堆排序算法*/
int HeapSort(struct DataType a[],int n)
{
int i;
struct DataType temp; //定义一个临时变量
for(i = n; i > 1; i--) /*这个 i>1(最后还有一个元素时不用排序,少一步,效率高一些) 与 i>0 都成功*/
{
CreatHeap(a,i); //使数组成为最大堆
temp = a[0]; //堆顶 a[0] 元素(为最大元素)和当前最大堆的最后一个元素交换
a[0] = a[i-1];
a[i-1] = temp;
}
return 0;
}
/*测试程序*/
int main()
{
int i;
int n = 21;
struct DataType test[21] = {1,16,45,87,23,5,9,34,10,6,26,64,5,7,89,6,24,100,4,7,19};
HeapSort(test,n); /*注意这个的参数及参数传递*/
for(i = 0; i < n; i++)
{
printf(" %d ",test[i].key);
}
printf("\n");
//system("pause"); //暂停
return 0;
}
下面的是书上的例子
#include <iostream>
using namespace std;
typedef int KeyType;
struct DataType
{
KeyType key;
};
/*创建最大堆*/
void CreatHeap(DataType a[],int n,int h)
{
int i,j,flag;
DataType temp;
i = h; // i 为要建堆的二叉树根结点下标
j = 2 * i +1; // j 为 i 的左孩子结点的下标
temp = a[i];
flag = 0;
//没左右孩子中值较大者重复向下筛选
while(j < n && flag != 1)
{
//寻找左、右孩子结点中的较大者,j 为其下标
if(j < n-1 && a[j].key < a[j+1].key) j++;
if(temp.key > a[j].key) // a[i].key > a[j].key
flag = 1; //标记结束筛选条件
else //否则把 a[j] 上移
{
a[i] = a[j];
i = j;
j = 2 * i +1;
}
}
a[i] = temp;
}
/*初始化创建最大堆算法*/
void InitCreatHeap(DataType a[],int n)
{
int i;
for(i = (n-1)/2; i >= 0; i--)
CreatHeap(a,n,i);
}
/*堆排序算法*/
void HeapSort(DataType a[],int n)
{
int i;
DataType temp;
InitCreatHeap(a,n); //初始化创建最大堆
for(i = n-1; i > 0; i--) //当前最大堆个数每次递减 1
{
//把堆顶 a[0] 元素和当前最大堆的最后一个元素交换
temp = a[0];
a[0] = a[i];
a[i] = temp;
CreatHeap(a,i,0); //调整根结点满足最大堆
}
}
/*测试程序*/
int main()
{
int i;
int n = 21;
struct DataType test[21] = {1,16,45,87,23,5,9,34,10,6,26,64,5,7,89,6,24,100,4,7,19};
HeapSort(test,n); /*注意这个的参数及参数传递*/
for(i = 0; i < n; i++)
{
printf(" %d ",test[i].key);
}
printf("\n");
//system("pause"); //暂停
return 0;
}