关于堆排序的学习总结
堆的定义
n个元素的序列{k1,k2,···,kn},当满足(k1 <= k2, ki <= k2i+1)或(k1 >= k2, ki >= k2i+1)时,可称之为堆。
若将堆看作二叉树,则有两种形式(大根堆,小根堆),即层序遍历每一层都比上一层小(大);而堆顶元素(完全二叉树的根)必为其序列的最大(小)值;
1-1大根堆与小根堆
堆的排序
其实堆排序可以用一句话来概括:“创建堆,用***最末值***替出***堆顶***,再重新***创建堆***。如此往复。”
但要注意一点,两次的***创建堆***相似但不完全一样。
第一次的创建堆是自下而上的,调用n/2次创建函数。
第二次的创建堆只需调用一次函数。
- 以下是堆排序的函数
void create_heap(int* arr,size_t len,int root) //创建大根堆
{
while(root*2 <= len)
{
int max = root*2;
if(max+1<len && arr[max-1] < arr[max]) //查找较大的那个子节点
max++;
if(arr[root-1] > arr[max-1]) //如发现无需调换子节点,说明已建好堆
return;
swap(arr[root-1],arr[max-1]); //与比根节点大的子节点进行替换
root = max; //将替换后的子节点作为根节点,进行下一层的比较
}
}
void heap_sort(int* arr,size_t len)
{
for(int i=len/2; i>0; i--) //创建大根堆(对无序序列),从最下层的树进行排序,至下而上
create_heap(arr,len,i);
for(int i=len-1; i>0; i--) //用最末节点替换提取根节点,再进行堆排序,重复n次.
{
swap(arr[0],arr[i]);
create_heap(arr,i,1);
}
show_sort_result(__func__,arr,len); //显示函数
}
堆排序的性能
其时间复杂度为O(nlogn),其运行时间主要耗费在***建初始堆***和调整建新堆时进行的反复***筛选***上。