码迷,mamicode.com
首页 > 编程语言 > 详细

排序3-堆排序

时间:2015-06-29 13:27:03      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:堆排序

基本思想

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

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

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

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

代码实现

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

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);
    }
}

测试代码

#include <iostream>
#include <cstring>
#include <ctime>
#include <cmath>
using namespace std;


#define ArraySize 100000


void 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.038s
Shell_sort2 runtime:   0.021s
Heap_Sort runtime:   0.004s

时间复杂度分析

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

参考资料

堆排序 - 维基百科,自由的百科全书
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/

排序3-堆排序

标签:堆排序

原文地址:http://blog.csdn.net/zwhlxl/article/details/46679265

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!