堆的定义:n个元素的序列Ki,K2,...,Kn{K_i,K_2,...,K_n}Ki,K2,...,Kn,当且仅当满足如下关系时,这个序列称为堆
Ki>=k2i+1,Ki>=K2i+2K_i>=k_{2i+1} ,K_i>=K_{2i+2}Ki>=k2i+1,Ki>=K2i+2 或者 Ki<=K2i+1,Ki<=K2i+2K_i<=K_{2i+1} ,K_i<=K_{2i+2}Ki<=K2i+1,Ki<=K2i+2
堆排序的基本思路:假设数据包含n个元素,对前n个元素构建最大堆,然后Swap(K0,Kn)Swap(K_0,K_n)Swap(K0,Kn) 对前n-1个元素构建最大堆,Swap(K0,Kn−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(n2n^2n2) | O(n2n^2n2) | O(n2n^2n2) | O(1) | 简单 | 不稳定 |
冒泡排序 | O(n2n^2n2) | O(n2n^2n2) | O(nnn) | O(1) | 简单 | 稳定 |
插入排序 | O(n2n^2n2) | O(n2n^2n2) | O(nnn) | O(1) | 简单 | 稳定 |
快速排序 | O(nlog2nnlog_2nnlog2n) | O(n2n^2n2) | O(nlog2nnlog_2nnlog2n) | O(log2nlog_2nlog2n) | 复杂 | 不稳定 |
归并排序 | O(nlog2nnlog_2nnlog2n) | O(nlog2nnlog_2nnlog2n) | O(nlog2nnlog_2nnlog2n) | O(n) | 复杂 | 稳定 |
堆排序 | O(nlog2nnlog_2nnlog2n) | O(nlog2nnlog_2nnlog2n) | O(nlog2nnlog_2nnlog2n) | O(1) | 复杂 | 不稳定 |
希尔排序 | O(n1.3n^{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(rrr) | 复杂 | 稳定 |