平均时间复杂度:O(nlogn) 最佳时间复杂度:O(nlogn) 最差时间复杂度:O(nlogn) 稳定性:不稳定
堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,
然后从R[1...n-2]中选择最大记录需比较n-2次。
事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,
因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。
堆排序为不稳定排序,不适合记录较少的排序。
#include <iostream>
#include <cstdio>
#include <algorithm>//c++11不需要 swap在std命名空间里面
/** 找到当前子树最大结点,放到父节点*/
void heapify(int arr[],int i,int len)
{
if(i < len)
{
int right = 2*i+2;
int left = 2*i+1;
int max_value = i;
if(right<len)
{
if(arr[right]>arr[max_value])
{
max_value = right;
}
}
if(left < len)
{
if(arr[left]>arr[max_value])
{
max_value = left;
}
}
if(max_value != i){
std::swap(arr[i],arr[max_value]);
/*int temp = arr[i];
arr[i] = arr[max_value];
arr[max_value] = temp;*/
heapify(arr,max_value,len);
}
}
}
/** 建堆操作*/
void max_heapify(int arr[], int len){
for(int i = len-1;i>=0;i--){
heapify(arr,i,len);
}
}
/**堆排序*/
void heap_sort(int arr[],int len){
for(int i = len-1;i>=0;i--){
max_heapify(arr,i+1);//缩减 i+1是当前数组的大小
std::swap(arr[0],arr[i]);
/*int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;*/
}
}
// 冒泡排序改进②
// 记录某次遍历时最后发生数据交换的位置pos,
// 由于pos位置之后的记录均已有序(或者交换到位),故在进行下一趟排序时只要扫描到pos位置即可。
void bubble_sort(int arr[], int len)
{
int j, k;
int flag;
flag = len;
while (flag > 0)
{
k = flag;
flag = 0;
for (j = 1; j < k; j++)
if (arr[j - 1] > arr[j])
{
std::swap(arr[j - 1], arr[j]);
flag = j;
}
}
}
int main()
{
int arr[]= {1,2,56,23,125,78,89,56,44,4,121,212,0,333};
int length = sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr,length);
printf("\n冒泡后:\t");
for(int i = 0;i<length;i++){
printf("%4d",arr[i]);
}
max_heapify(arr,length);
printf("\n\n建堆后:\t");
for(int i = 0;i<length;i++){
printf("%4d",arr[i]);
}
printf("\n\n排序后:\t");
heap_sort(arr,length);
for(int i = 0;i<length;i++){
printf("%4d",arr[i]);
}
printf("\n");
return 0;
}
冒泡优化:https://github.com/7-sevens/algorithm/tree/master/sort