堆是具有以下性质的完全二叉树:每个结点的值都大于或等于左右孩子结点的值,称之为大顶堆,或者每个结点的值都小于或等于左右孩子结点的值,称之为小顶堆。堆排序由以下步骤构成:
1.将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆。
2.将堆顶元素与末尾元素进行交换-将最大元素“沉”到数组末端
3.重新调整结构,使其满足堆的定义,然后继续交换堆顶与当前末尾元素。直到整个序列有序。
//堆排序
/*******************************************************************/
//调整堆为大顶堆
void adjustHeap(int *a,int i, int size)
{
int lchild = 2 * i; //左孩子
int rchild = 2 * i + 1; //右孩子
int maxIndex = i; //最大值的下标
if (i<=size/2)
{
if (lchild <= size && a[lchild] > a[maxIndex])
{
maxIndex = lchild;
}
if (rchild <= size && a[rchild] > a[maxIndex])
{
maxIndex = rchild;
}
if (maxIndex != i)
{
int temp = a[maxIndex];
a[maxIndex] = a[i];
a[i] = temp;
adjustHeap(a, maxIndex, size); //i<=size/2是防止此处对叶子节点进行调整
}
}
}
//建立大顶堆
void buildHeap(int *a, int size)
{
int parentNode = size / 2; //最大非叶子节点
for (int i=parentNode;i>=1;i--)
{
adjustHeap(a, i, size);
}
}
//堆排序实现
void heapSort(int *a, int size)
{
for (int i=size;i>1;i--)
{
buildHeap(a, i);
int temp = a[i];
a[i] = a[1];
a[1] = temp;
}
}