堆排序

堆排序,顾名思义利用堆的性质进行排序。堆都有哪些性质,比如:一堆沙子、一堆泥土

二叉堆实际上是一课完全二叉树,同时满足:父结点的键值总是大于或等于(小于或等于)任何一个子结点的键值

当父结点的键值总是大于或等于任何一个子结点的键值时称为 最大堆

当父结点的键值总是小于或等于任何一个子结点的键值时称为 最小堆

二叉堆又简称为 堆,通常用数组来实现

i 结点的父结点的下标是: (i-1) / 2 , 左子树的下标是:2 * i + 1 , 又子树的下标是: 2 * i + 2

堆排序中首先需要解决的问题是将数组进行堆化(下面以最小堆为例)

给定数组 a[] = {9,12,17,30,50,20,60,65,4,19} ;

初始化堆如下图:

对数组进行堆化后如下图:

#include<stdio.h>

void makeMinHead(int a[] , int n)    {
    for(int i = n / 2 - 1 ; i >= 0 ; i--)    {
        int k = i ;
        int temp = a[k] ;
        for(int j = 2 * k + 1 ; j < n ; )    {
            if(j + 1 < n && a[j+1] < a[j])
                j++ ;
            if(temp <= a[j])
                break ;
            a[k] = a[j] ;
            k = j ;
            j = 2 * k + 1 ; 
        }
        a[k] = temp ;
    }    
}

int main()    {
    int a[] = {9,12,17,30,50,20,60,65,4,19} ;
    makeMinHead(a,10) ;
    for(int i = 0 ; i < 10 ; i++)
        printf("%d ",a[i]) ;
    printf("\n") ;
    return 0 ;
}

堆化数组之后,第0个数据是堆中最小的数据,删除第0个元素,同时把最后一个元素放到第0个元素的位置上,不断缩小堆中元素,则第一小,第二小,第三小……分别被查找出来,堆排序结束;

具体过程如下:

#include<stdio.h>

void makeMinHead(int a[] , int n)    {                
    for(int i = n / 2 - 1 ; i >= 0 ; i--)    {    // 对数组进行堆化 
        int k = i ;                                // 从第一个非叶子结点开始 
        int temp = a[k] ;            
        for(int j = 2 * k + 1 ; j < n ; )    {    // 和插入排序类似 
            if(j + 1 < n && a[j+1] < a[j])        // 左子树和右子树中取最小值 
                j++ ;
            if(temp <= a[j])                    // 如果父结点的键值小于或等于两个儿子结点中的最小值,这不再需要调整 
                break ;
            a[k] = a[j] ;                        //    如果父结点的键值大于两个儿子结点中的最小值,继续交换 
            k = j ;
            j = 2 * k + 1 ; 
        }
        a[k] = temp ;
    }    
}

void Swap(int &a , int &b)    {
    a = a ^ b ;
    b = a ^ b ;
    a = a ^ b ;
}

void HeadSort(int a[] , int n)    {                    // 堆排序过程 
    for(int i = n-1 ; i > 0 ; i--)    {                // 每调整一次,找出一个最小值 
        int temp = a[0] ;                            // 将第0个数据放到合适的位置上 
        int k = 0 ;
        for(int j = 2 * k + 1 ; j <= i ;)    {
            if(j + 1 <= i && a[j + 1] < a[j])
                j++ ;
            if(temp <= a[j])
                break ;
            a[k] = a[j] ;
            k = j ;
            j = 2 * k + 1 ;
        }
        a[k] = temp ;
        Swap(a[0] , a[i]) ;                        // 将最小值放到数组后边 
    }
} 

int main()    {
    int a[] = {9,12,17,30,50,20,60,65,4,19} ;
    makeMinHead(a,10) ;
    Swap(a[0],a[9]) ;
    HeadSort(a,9) ;
    for(int i = 9 ; i >= 0 ; i--)
        printf("%d ",a[i]) ;
    printf("\n") ;
    return 0 ;
}

 

posted @ 2015-04-18 16:36  scott_dingg  阅读(193)  评论(0编辑  收藏  举报