zoukankan      html  css  js  c++  java
  • 堆排序

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

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

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

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

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

    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("
    ") ;
        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("
    ") ;
        return 0 ;
    }
  • 相关阅读:
    C++中的名字重整技术
    Linux下C++开发常用命令
    《Effective C++(第三版)》 的55条建议
    我也介绍下sizeof与strlen的区别
    POJ
    HDU
    HDU-1754-I Hate It(单点更新+区间查询)
    HDU多校1003-Divide the Stones(构造)
    Just an Old Puzzle(2019多校1007)
    Idiomatic Phrases Game(最短路+注意坑点)
  • 原文地址:https://www.cnblogs.com/scottdinggo/p/4437640.html
Copyright © 2011-2022 走看看