堆的定义:n个元素的序列 K i , K 2 , . . . , K n {K_i,K_2,...,K_n} Ki,K2,...,Kn,当且仅当满足如下关系时,这个序列称为堆
K i > = k 2 i + 1 , K i > = K 2 i + 2 K_i>=k_{2i+1} ,K_i>=K_{2i+2} Ki>=k2i+1,Ki>=K2i+2 或者 K i < = K 2 i + 1 , K i < = K 2 i + 2 K_i<=K_{2i+1} ,K_i<=K_{2i+2} Ki<=K2i+1,Ki<=K2i+2
堆排序的基本思路:假设数据包含n个元素,对前n个元素构建最大堆,然后 S w a p ( K 0 , K n ) Swap(K_0,K_n) Swap(K0,Kn) 对前n-1个元素构建最大堆, S w a p ( K 0 , K n − 1 ) Swap(K_0,K_{n-1}) Swap(K0,Kn−1),重复此过程,便得到一个有序数组;
如何构建最大堆呢,首先要从最后一个非叶子节点开始,从左向右,从下至上进行调整;
public void AdjustUp(int arr[], int i, int n)
{
int j = i * 2 + 1;//子节点
while (j<n)
{
if (j+1<n && arr[j] < arr[j + 1])//子节点中找较小的
{
j++;
}
if (arr[i] > arr[j])
{
break;
}
swap(arr,i,j);
i = j;
j = i * 2 + 1;
}
}
public void MakeHeap(int arr[], int n)//建堆
{
int i = 0;
for (i = n / 2 - 1; i >= 0; i--)//((n-1)*2)+1 =n/2-1
{
AdjustUp(arr, i, n);
}
}
public void HeapSort(int arr[],int len)
{
int i = 0;
MakeHeap(arr, len);
for (i = len - 1; i >= 0; i--)
{
swap(arr,i, 0);
AdjustUp(arr, 0, i);
}
}
public void swap(int[] arr,int a,int b){
int temp = arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
常用排序算法比较
名称 | 平均时间复杂度 | 最差时间复杂度 | 最好时间复杂度 | 空间复杂度 | 复杂度 | 稳定性 |
---|---|---|---|---|---|---|
选择排序 | O( n 2 n^2 n2) | O( n 2 n^2 n2) | O( n 2 n^2 n2) | O(1) | 简单 | 不稳定 |
冒泡排序 | O( n 2 n^2 n2) | O( n 2 n^2 n2) | O( n n n) | O(1) | 简单 | 稳定 |
插入排序 | O( n 2 n^2 n2) | O( n 2 n^2 n2) | O( n n n) | O(1) | 简单 | 稳定 |
快速排序 | O( n l o g 2 n nlog_2n nlog2n) | O( n 2 n^2 n2) | O( n l o g 2 n nlog_2n nlog2n) | O( l o g 2 n log_2n log2n) | 复杂 | 不稳定 |
归并排序 | O( n l o g 2 n nlog_2n nlog2n) | O( n l o g 2 n nlog_2n nlog2n) | O( n l o g 2 n nlog_2n nlog2n) | O(n) | 复杂 | 稳定 |
堆排序 | O( n l o g 2 n nlog_2n nlog2n) | O( n l o g 2 n nlog_2n nlog2n) | O( n l o g 2 n nlog_2n nlog2n) | O(1) | 复杂 | 不稳定 |
希尔排序 | O( n 1.3 n^{1.3} n1.3) | O(1) | 复杂 | 不稳定 | ||
基数排序 | O( d ( n + r ) d(n+r) d(n+r)) | O( d ( n + r ) d(n+r) d(n+r)) | O( d ( n + r ) d(n+r) d(n+r)) | O( r r r) | 复杂 | 稳定 |