排序----堆排序

排序----堆排序

插入、合并、堆、快速排序通过对数组中的元素进行比较来实现,对任何n个输入来说,最坏运行时间下界为Ω(n*lgn)。

注:lgn是log2(n)

A是一个任意数组,这里举例为A[10] = {16,14,10,8,7,9,3,2,4,1}

将数组以二叉树形式展示,结点下标与数组下标对应:


i的父节点parent(i) = i/2

左节点left(i) = 2i 

右节点right(i) = 2i + 1

1.将一个以i为根的子树转换为子最大堆

最大堆是满足下列条件的完全二叉树:除了根以外的每个节点i,都有A[parent(i)] >= A[i]

转换过程:

MAX-HEAPIFY(A,i)

{

   l = left(i)

   r = right(i)

   heap-size[A] = lenght(A)

   if l <= heap-size[A] && a[l] > a[i]

   {

       then largest = l

       else largest = i

   }

   if r <= heap-size[A] && a[r] > a[largest]

   {   then largest = r}

   if i != largest

   {  

       then exchange( a[i], a[largest] ) 

          MAX-HEAPIFY(A,largest)

   }

}

运行时间为O(lgn)

2.创建最大堆

一棵n个元素组成的二叉树中,元素A[n/2 + 1], A[n/2 + 2],...,A[n]都是树的叶子,因此每个都可以看成是只有一个元素的堆而无需转换成最大堆

建堆过程:

BUILD-MAX-HEAPIFY(A)

heap-size[A] = lenght(A)

for (i = heap-size[A]/2; i >= 1; i--)

{

    MAX-HEAPIFY(A,i)

}

初步分析每次调用MAX-HEAPIFY(A,i)所用的时间为O(lgn),一共调用了O(n)次,故该算法运行时间为O(n*lgn);实际上,在树中不同高度的结点处运行MAX-HEAPIFY的时间不同,大部分结点的高度都较小。一个n元素堆的高度为lgn,在任意高度上,最多有n/2^(h + 1)个结点,故BUILD-MAX-HEAPIFY更准确的运行时间为:O(n)

3.排序

HEAPSOTR(A)

BUILD-MAX-HEAPIFY(A)

for (i = length(A); i >= 2; i--)

{

    exchange(A[i], A[1])

 MAX-HEAPIFY(A,1)

    heap-size[A] = heap-size[A] -1 

}

HEAPSOTR过程的时间代价为O(n*lgn),其中BUILD-MAX-HEAPIFY的时间代价为O(n),n-1次MAX-HEAPIFY的时间代价为O(lgn)


代码实现:

/*
 *name:     max_heap.c
 *author:     ls
 *date:        2012-04-26
 *destribution:    堆排序实现
 */
#include <stdio.h>

//创建最大树子树
void max_heapify(int array[], int len, int i)
{    
    int left,right;
    int largest;
    int tmp;
    
    left = 2 * i + 1;
    right = 2 * i + 2;
    
    //找出该节点与其左右节点的最大节点
    if (left <= len - 1 && right <= len - 1)
    {
        if (array[i] >= array[left])
        {
            largest = i;
        }
        else
        {
            largest = left;
        }
        if (array[right] >= array[largest])
        {
            largest = right;
        }
    
        if (i != largest)
        {
            //将该节点的值替换为三个节点中的最大值
            tmp = array[i];
            array[i] = array[largest];
            array[largest] = tmp;
        
            //递归调用,如果右节点号大于最大节点数,则停止调用
            if (right <= len - 1)
            {
                max_heapify(array, len, largest);
            }
        }
    }
}

//创建最大树
void create_max_heapify(int array[], int len)
{
    int i;    
    
    //树中只有第0个节点到第(len - 2)/2个节点是子树的根,后面的节点不需要建最大子树
    i = (len - 2)/2;
    
    for (; i >= 0; i--)
    {
        max_heapify(array, len, i);
    }
}

int main()
{
    int i, tmp;
    int len = 12;
    int array[12] = {11, 3, 6, 4, 9, 12, 2, 7, 8, 5, 10, 1};

    create_max_heapify(array, len);
        
    for (i = len - 1; i >= 1; i--)
    {        
        tmp = array[i];
        array[i] = array[0];
        array[0] = tmp;
        
        len--;
        max_heapify(array, len, 0);
    }

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

}

http://blog.csdn.net/sever2012/article/list/2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值