堆是一种树形结构,堆排序是对直接选择排序的有效改进。实现堆排序需要解决三个问题:
1.构建完全二叉树:先把待排序序列构建成一棵完全二叉树。
2.把无序序列建成的完全二叉树调成一个有序堆。
然后根据以下定义建堆:
n个元素的序列{k1, k2, …., kn}当且满足下述关系时,称之为堆。
前者称为小顶堆(小根堆),后者称为大顶堆(大根堆)。
从一个无序序列建堆的过程就是一个反复“筛选”的过程。“筛选”只需从第个元素开始(完全二叉树中最后一个非终端结点)。
堆排序的最坏时间复杂度为O(nlog2n),它的平均性能较接近于最坏情况。在记录数较少的情况下,不适宜用堆排序。堆排序是就地排序,辅助空间为O(1),它是不稳定的排序。
Java代码:
public class HeapSort {
public static void main(String[] args) {
int array[] = {5, 18, 151, 138, 160, 63, 174, 169, 79, 200};
showArray(array);
System.out.println("\n排序后");
heapSort(array);
showArray(array);
}
/*
* a 待排数组 rootIndex 本次堆化的根 maxHeapIndex 本次堆化所达到的堆数组最大索引
*/
private static void maxHeapify(int a[],int rootIndex,int maxHeapIndex)
{
int lChild = rootIndex*2+1;
int rChild = rootIndex*2+2;
int largeIndex = rootIndex;
if(lChild<=maxHeapIndex && a[lChild]>a[rootIndex])
largeIndex = lChild;
if(rChild<=maxHeapIndex && a[rChild]>a[largeIndex])
largeIndex = rChild;
if(largeIndex != rootIndex)
{
swap(a,largeIndex,rootIndex);
maxHeapify(a,largeIndex,maxHeapIndex);
}
}
private static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
private static void heapSort(int[] a) {
int i = 0;
int maxHeapIndex = a.length -1;
//首先建立一个堆,大根堆是要满足父亲节点都是大于子节点的
for(i=(maxHeapIndex-1)/2;i>=0;i--)
{
maxHeapify(a,i,maxHeapIndex);
}
for(i=maxHeapIndex;i>=1;i--)
{
swap(a,0,i);
//交换之后,继续堆化时,堆数组的索引要减去1,把最大的数字就直接保存到末尾了
maxHeapify(a,0,i-1);
}
}
private static void showArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
c代码:
//堆排序
#include<stdio.h>
#include<malloc.h>
void showArray(int a[],int len){
for(int i=0;i<len;i++){
printf("%d ",a[i]);
}
}
void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
/*
a 待排数组
rootIndex 本次堆化的根
maxHeapIndex 本次堆化所达到的堆数组最大索引
*/
void maxHeapify(int a[],int rootIndex,int maxHeapIndex)
{
int lChild = rootIndex*2+1;
int rChild = rootIndex*2+2;
int largeIndex = rootIndex;
if(lChild<=maxHeapIndex && a[lChild]>a[rootIndex])
largeIndex = lChild;
if(rChild<=maxHeapIndex && a[rChild]>a[largeIndex])
largeIndex = rChild;
if(largeIndex != rootIndex)
{
swap(&a[largeIndex],&a[rootIndex]);
maxHeapify(a,largeIndex,maxHeapIndex);
}
}
/*
a: 待排序数组长度
len : 数组长度
*/
void heapSort(int a[],int len)
{
int i = 0;
int maxHeapIndex = len -1;
//首先建立一个堆,大根堆是要满足父亲节点都是大于子节点的
for(i=(maxHeapIndex-1)/2;i>=0;i--)
{
maxHeapify(a,i,maxHeapIndex);
}
for(i=maxHeapIndex;i>=1;i--)
{
swap(&a[0],&a[i]);
//交换之后,继续堆化时,堆数组的索引要减去1,把最大的数字就直接保存到末尾了
maxHeapify(a,0,i-1);
}
}
int main()
{
int a[] = {5, 18, 151, 138, 160, 63, 174, 169, 79, 200};
int len = sizeof(a)/sizeof(int);
showArray(a,len);
heapSort(a,len);
printf("\n排序后:\n");
showArray(a,len);
return 0;
}
堆排序就是先建立堆,然后对从最后一个非叶子节点开始,进行不断交换的过程