堆排序

这里介绍了堆的操作 https://www.cnblogs.com/zuofaqi/p/9665619.html

堆还可以用来做堆排序,其过程是:对于从小到大的排序,使用最大堆。建堆之后,交换第一个元素和最后一个堆元素,这样,最后一个堆元素A[n-1]就是最大值,而A[0...n-2]的堆结构就被破坏了,通过堆顶元素的下沉操作,使A[0...n-2]再次成为一个堆。再交换第一个元素和最后一个堆元素,循环下去,最后,整个堆都是有序的。

void heapSort(int* arr, int heapsize)
{
    // 建堆
    adjust_by_sink(arr, heapsize);
    
    while (heapsize > 1)
    {
        int tmp = arr[0];
        arr[0] = arr[heapsize-1];
        arr[heapsize-1] = tmp;
        // 堆长减1, 新堆首元素下沉
        heapsize--;
        sink(arr, 0, heapsize);
    }
}

通过这个过程,我们可以知道,堆排序是原址排序。同时,堆排序是不稳定排序,比如 [2,6,8,5,0,1,7,7]这个数组,在使用下沉法建堆的时候,两个7的相对位置就变了。堆排序时间复杂度是O(nlogn)

完整代码:

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define ARRLEN 100

#define LEFT(idx) (((idx)<<1)+1)
#define RIGHT(idx) (((idx)<<1)+2)
#define PARENT(idx) (((idx)-1)>>1)


// 下沉
void sink(int* arr, int index, int heapsize)
{
    // 左子树节点超出堆长度范围
    if (LEFT(index) > heapsize-1)
    {
        return;
    }

    int maxidx = -1;
    // 右子树节点超出堆长度范围,或者左节点的值比右节点的值大
    if (RIGHT(index) > heapsize-1 || (arr[LEFT(index)] > arr[RIGHT(index)]))
    {
        maxidx = LEFT(index);
    }
    else
    {
        maxidx = RIGHT(index);
    }

    if (maxidx != -1 && arr[maxidx] > arr[index])
    {
        int tmp = arr[maxidx];
        arr[maxidx] = arr[index];
        arr[index] = tmp;
        sink(arr, maxidx, heapsize);
    }
}

// 上浮
void upward(int* arr, int index, int heapsize)
{
    if (0 == index)
    {
        return;
    }

    if (arr[PARENT(index)] < arr[index])
    {
        int tmp = arr[index];
        arr[index] = arr[PARENT(index)];
        arr[PARENT(index)] = tmp;
        upward(arr, PARENT(index), heapsize);
    }
}

void adjust_by_sink(int* arr, int heapsize)
{
    // 下沉法,从最后一个非叶子节点开始,到根节点,依次执行下沉
    for (int i = PARENT(heapsize-1); i >= 0; i--)
    {
        sink(arr, i, heapsize);
    }
}

void adjust_by_upward(int* arr, int heapsize)
{
    // 上浮法,从根节点到最后一个节点,依次执行上浮
    for (int i = 0; i < heapsize; i++)
    {
        upward(arr, i, heapsize);
    }
}

int insert(int* arr, int value, int& heapsize)
{
    if (heapsize > ARRLEN)
    {
        return -1;
    }

    arr[heapsize] = value;
    upward(arr, heapsize, heapsize+1);
    heapsize++;

    return 0;
}

void del(int* arr, int& heapsize)
{
    if (heapsize <= 0)
    {
        return;
    }

    arr[0] = arr[heapsize-1];
    heapsize--;
    sink(arr, 0, heapsize);
}

void heapSort(int* arr, int heapsize)
{
    // 建堆
    adjust_by_sink(arr, heapsize);
    
    while (heapsize > 1)
    {
        int tmp = arr[0];
        arr[0] = arr[heapsize-1];
        arr[heapsize-1] = tmp;
        // 堆长减1, 新堆首元素下沉
        heapsize--;
        sink(arr, 0, heapsize);
    }
}

int main()
{
    int arr[ARRLEN] = {2,3,4,5,1,2,3,7};
    int heapsize = 8;

    heapSort(arr, heapsize);

    for (int i = 0; i < heapsize; i++)
    {
        printf("%d\n", arr[i]);
    }

    return 0;
}

 

posted @ 2018-09-18 21:13  二狗啸地  阅读(222)  评论(0编辑  收藏  举报