排序3-堆排序

来源:互联网 发布:windows自带桌面图片 编辑:程序博客网 时间:2024/05/17 22:29

基本思想

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以看作是对选择排序的改进。
通常堆是通过一维数组来实现的。在起始数组为0的情形中:

  • 父节点i的左子节点在位置(2*i+1);
  • 父节点i的右子节点在位置(2*i+2);
  • 子节点i的父节点在位置floor((i-1)/2);

在堆的数据结构中,堆中的最大值总是位于根节点。堆中定义以下几种操作:

  • 最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
  • 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
  • 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

时间复杂度分析

建立N个元素的二叉堆需要花费O(n),在正式排序时,第i次取堆顶的数据事,重建堆需要用O(logi),总共取n1次堆顶,所以重建堆需要花费O(nlogn)。因此,堆排序的时间复杂度为O(nlogn),又因为堆排序对原数据的初始状态不敏感,所以最好、最坏和平均时间复杂度均为O(nlogn); 可以原地进行,空间复杂度O(1)

代码实现

最大堆调整有递归和非递归实现方式。

void Heap_adjust(int arr[], int index, int len){    while(true)    {        int iMax = index;        int iLeft = 2 * index + 1;        int iRight = 2 * index + 2;        if(iLeft < len && arr[index] < arr[iLeft])            iMax = iLeft;        if(iRight < len && arr[iMax] < arr[iRight])            iMax = iRight;        if(iMax != index)        {            swap(arr[index], arr[iMax]);            index = iMax;        }        else             break;    }}void Heap_adjust2(int arr[], int index, int len){    int iMax = index;    int iLeft = 2 * index + 1;    int iRight = 2 * index + 2;    if(iLeft < len && arr[index] < arr[iLeft])        iMax = iLeft;    if(iRight < len && arr[iMax] < arr[iRight])        iMax = iRight;    if(iMax != index)    {        swap(arr[index], arr[iMax]);        Heap_adjust2(arr, iMax, len);    }}void Build_maxheap(int arr[], int len){    for(int i = len / 2; i >= 0; i --)    {        Heap_adjust(arr, i , len);    }}void Heap_Sort(int arr[], int len){    Build_maxheap(arr, len);    for(int i = len - 1; i > 0; i --)    {        swap(arr[0], arr[i]);        Heap_adjust(arr, 0, i);    }}

测试代码

#include <iostream>#include <cstring>#include <ctime>#include <cmath>using namespace std;#define ArraySize 100000void swap(int *x, int *y){    int temp;    temp = *x;    *x   = *y;    *y   = temp;}void Bubble_sort(int arr[], int len){    for(int i = 0; i < len; i ++)    {        for(int j = i + 1; j < len; j ++)            if(arr[i] > arr[j])                swap(arr[i], arr[j]);    }}void Bubble_sort1(int arr[], int len){    for(int i = 0; i < len; i ++)    {        for(int j = len - 1; j >= i; j --)        {            if(arr[i] > arr[j])                swap(arr[i], arr[j]);        }    }}void Bubble_sort2(int arr[], int len){    bool flag = true;    while(flag)    {        flag = false;        for(int i = 0; i < len; i ++)            for(int j = len - 1; j >= i; j --)                if(arr[i] > arr[j])                    swap(arr[i], arr[j]);    }}void Slect_sort(int arr[], int len){    for(int i = 0; i < len; i ++)    {        int min_index = i ;        for(int j = i + 1; j < len; j ++)        {            if(arr[min_index] > arr[j])                min_index = j;        }        if(i != min_index)            swap(arr[i],arr[min_index]);    }}void Insert_sort(int arr[], int len){    for(int i= 1; i < len; i ++)    {           int key = arr[i];        int j = i;        while(j && arr[j - 1] > key)        {            arr[j] = arr[j - 1];            j --;        }        arr[j] = key;    }}void Shell_sort(int arr[], int len){    int increment = len / 2;    while(increment)    {        for(int i = increment; i < len; i ++)        {            int key = arr[i];            /*int j ;            for(j = i; j >= increment; j -= increment)            {                if(arr[j-increment] > key )                    arr[j] = arr[j-increment];                else                     break;            }*/            int j = i;            while(j >= increment && arr[j-increment] > key)            {                arr[j] = arr[j-increment];                j -= increment;            }            arr[j] = key;        }        increment /= 2;    }}void Shell_sort1(int arr[], int len){    int increment = 0;    for(increment = len/2; increment > 0; increment /=2)    {        for(int i = increment; i < len; i++)        {            int key = arr[i];            int j = 0;            for(j = i; j >= increment; j -=increment)            {                if(arr[j-increment] > key)                    arr[j] = arr[j-increment];                else                     break;            }            arr[j] = key;        }    }}void Shell_sort2(int arr[], int len){    int index = log( 2*len + 1) / log(3.0);    //cout << index << endl;    int increment = ( pow(3.0, index) - 1 ) / 2;    //cout << increment << endl;    while(increment)    {        for(int i = increment; i < len; i ++)        {            int key = arr[i];            /*int j ;            for(j = i; j >= increment; j -= increment)            {                if(arr[j-increment] > key )                    arr[j] = arr[j-increment];                else                     break;            }*/            int j = i;            while(j >= increment && arr[j-increment] > key)            {                arr[j] = arr[j-increment];                j -= increment;            }            arr[j] = key;        }        index -= 1;        increment = ( pow(3.0, index) - 1 ) / 2;    }}void Heap_adjust(int arr[], int index, int len){    while(true)    {        int iMax = index;        int iLeft = 2 * index + 1;        int iRight = 2 * index + 2;        if(iLeft < len && arr[index] < arr[iLeft])            iMax = iLeft;        if(iRight < len && arr[index] < arr[iRight])            iMax = iRight;        if(iMax != index)        {            swap(arr[index], arr[iMax]);            index = iMax;        }        else             break;    }}void Heap_adjust2(int arr[], int index, int len){    int iMax = index;    int iLeft = 2 * index + 1;    int iRight = 2 * index + 2;    if(iLeft < len && arr[index] < arr[iLeft])        iMax = iLeft;    if(iRight < len && arr[index] < arr[iRight])        iMax = iRight;    if(iMax != index)    {        swap(arr[index], arr[iMax]);        Heap_adjust2(arr, iMax, len);    }}void Build_maxheap(int arr[], int len){    for(int i = len / 2; i >= 0; i --)    {        Heap_adjust(arr, i , len);    }}void Heap_Sort(int arr[], int len){    Build_maxheap(arr, len);    for(int i = len - 1; i > 0; i --)    {        swap(arr[0], arr[i]);        Heap_adjust(arr, 0, i);    }}void Print_array(int arr[], int len){    for(int i = 0; i < len; i++)    {        cout << arr[i] << " ";    }    cout << endl;}int main(int argc, char const *argv[]){    /* code */    int Array[ArraySize];    int Array1[ArraySize];    int Array2[ArraySize];    time_t begin , end;    srand(time(NULL));    for(int i = 0; i < ArraySize; i ++)    {        Array[i] = rand()%ArraySize;        //cout << Array[i] << " ";    }    memcpy(Array1, Array, ArraySize * sizeof(Array1[0]));    memcpy(Array2, Array, ArraySize * sizeof(Array2[0]));//  Print_array(Array, ArraySize);/*  begin = clock();    Bubble_sort2(Array, ArraySize);    end = clock();    cout << "Bubble_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Slect_sort(Array1, ArraySize);    end = clock();    cout << "Slect_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Insert_sort(Array2, ArraySize);    end = clock();    cout << "Insert_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;*/     begin = clock();    Shell_sort1(Array1, ArraySize);    end = clock();    cout << "Shell_sort1 runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Shell_sort2(Array2, ArraySize);    end = clock();    cout << "Shell_sort2 runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Heap_Sort(Array, ArraySize);    end = clock();    cout << "Heap_Sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    //Print_array(Array2, ArraySize);    return 0;}

运行结果如下:

Shell_sort1 runtime:   0.038sShell_sort2 runtime:   0.021sHeap_Sort runtime:   0.026s

参考资料

堆排序 - 维基百科,自由的百科全书
https://zh.wikipedia.org/wiki/%E5%A0%86%E6%8E%92%E5%BA%8F
常见排序算法 - 堆排序 (Heap Sort) | bubkoo
http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/

0 0
原创粉丝点击