Stay Hungry,Stay Foolish!

算法-堆排序

什么是堆?

http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html

  n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

  情形1:ki <= k2i 且ki <= k2i+1 最小化堆小顶堆

  情形2:ki >= k2i 且ki >= k2i+1化堆大顶堆

 

  若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。

  由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

什么是堆排序?

http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html

  若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序

堆的存储

  一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+1和2*i+2。

二叉树左右儿子序关系证明

 

堆存储中 节点i 和 儿子的关系 为什么是 2i?

 

 

 

 

 

代码实现

https://github.com/fanqingsong/code-snippet/blob/master/C/heapSort/heapSort.c

其中CreateHeap为创建堆过程, 其实现了对最大元素选择到堆顶的操作, 此步骤保证, 每一个非叶子节点 都是一个 小的 子堆, 保证了部分有序。 见代码中的注释。

每一步的调整, 保证了从对树根到树叶的一次遍历。


#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
#include <ctype.h>

typedef enum returnType {
    FAIL = 0,
    SUCCESS,
} E_RETURN_TYPE;
    
typedef enum boolType {
    FALSE = 0,
    TRUE,
} E_BOOL_TYPE;

void printArr(int arr[], int size)
{
    int i = 0;

    printf("arr element is \n");

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

void SwapValue(int arr[], int index1, int index2)
{
    int tmp = arr[index1];

    arr[index1] = arr[index2];

    arr[index2] = tmp;
}

// select the extreme value to 0 element, 
// 0~i-1 is non order list, and 0 element break the heap
void HeapAdjust(int arr[], int breakIndex, int lastIndex)
{
    int breakVal = 0;
    int leftChildIdx = 0;
    int leftVal = 0;
    int rightVal = 0;

    // condiction is predicting that the left child of breaking node is existing
    while ( (leftChildIdx=2*breakIndex+1) <= lastIndex )
    {
        leftVal = arr[leftChildIdx];
        rightVal = arr[leftChildIdx+1];
        breakVal = arr[breakIndex];

        // right child is beyond range, set its value to minmun value
        if (leftChildIdx+1 > lastIndex)
        {
            rightVal = 0X1 << (sizeof(int)*8 -1);
        }

        // find the max, swap with break node
        if ( leftVal > rightVal )
        {
                if ( breakVal < leftVal )
                {
                    SwapValue(arr, breakIndex, leftChildIdx);
                    breakIndex = leftChildIdx;
                }
                else
                {
                    // break node is max, no more action need to be done
                    break;
                }
        }
        else
        {
                if ( breakVal < rightVal )
                {
                    SwapValue(arr, breakIndex, leftChildIdx+1);
                    breakIndex = leftChildIdx+1;
                }
                else
                {
                    // break node is max, no more action need to be done
                    break;
                }
        }
    }
}

// translate arr to heap with max top(0 index element is  max)
E_RETURN_TYPE CreateHeap(int arr[], int lastIdx)
{
    int i = 0;
    int lastNonLeafIdx = lastIdx/2;

    // for creating a heap, must adjust from last non leaf node to 0 index node
    /*
            0            ----- 0 height
          1  2          ----- 1 height
        .........
        x      y .. z   ----- n height
      x1 x2             ----- n+1 height
      note: as above, lastNonLeafIdx is x,  y..z node has no child
      first, for handling n height node(x),   we get the max of  x, x1, x2, save as x
      second, for handling n-1 height nodes( .... ), we get the max of the tree with every node as root
      ...
        until reach 0 height, we get the max of tree with 0 as root, ie we get max top heap
    */
    for ( i=lastNonLeafIdx; i>=0; i-- )
    {
        HeapAdjust(arr, i, lastIdx);
printf("--------- enter CreateHeap HeapAdjust %d\n", i);
    printArr(arr, lastIdx+1);
    }
}

E_RETURN_TYPE HeapSort(int arr[], int size)
{
    int i = 0;

    CreateHeap(arr, size-1);
printf("--------- after CreateHeap");
    printArr(arr, size);

    /* execute size-1 times loop  */
    for ( i=size-1; i>0; i-- )
    {
        // now arr[i] is the extreme value from 0 ~ i
        SwapValue(arr, 0, i);

        // 0~i-1 is non order list, and 0 element break the heap
        HeapAdjust(arr, 0, i-1);        
    }
}

int main(void)
{
    int arr [] = {8, 5, 6, 7};

printf("--------- before heap sort");
    printArr(arr, sizeof(arr)/sizeof(int));

    HeapSort(arr, sizeof(arr)/sizeof(int));
    
printf("--------- after heap sort");
    printArr(arr, sizeof(arr)/sizeof(int));
}


    Status API Training Shop Blog About Pricing 

    © 2016 GitHub, Inc. Terms Privacy Security Contact Help 

 

posted @ 2016-01-10 23:20  lightsong  阅读(286)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel