美文网首页
堆的相关操作与堆排序

堆的相关操作与堆排序

作者: ___Qian___ | 来源:发表于2019-03-08 10:42 被阅读0次

    堆中插入、删除元素

    先看图解:


    堆的插入与删除图解

    堆中插入元素

    插入元素总是插入在数组中的最后一个位置,然后从其父节点依次向上调整堆,执行元素“上浮”操作。

    //在最小堆中加入新的数据nNum
    void addNumber(int[] a, int n, int nNum)
    {
        a[n] = nNum;
        fixup(a, n);
    }
    
    //  新加入i结点  其父结点为(i - 1) / 2
    void fixup(int[] a, int i)
    {
        int j, temp;
        
        
        j = (i - 1) / 2;      //父结点
        while (j >= 0 && i != 0)     
        {
            if (a[j] <= a[i])       
                break;
            //父节点比当前节点大
            swap(a,i,j);    //当前节点与它的父节点交换,上浮
    
            i = j;      //继续向上调整堆
            j = (i - 1) / 2;
        }
        
    }
    //更简洁的写法:
    void fixup2(int[] a, int i)
    {
        for (int j = (i - 1) / 2; 
               (j >= 0 && i != 0)&& a[i] > a[j];
                i = j, j = (i - 1) / 2)
    
            swap(a, i, j);
    }
    

    堆中删除元素

    删除元素时,总是删除堆顶元素,后将堆中最后一个元素放置对顶,从堆顶到叶子节点依次向下调整堆,执行元素“下沉操作”。

    //在最小堆中删除数
    void deleteNumber(int[] a, int n)
    {
        swap(a[0], a[n - 1]);
        fixdown(a, 0, n - 1);
    }
    //  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
    void fixdown(int[] a, int i, int n)
    {
        int j, temp;
     
        temp = a[i];
        j = 2 * i + 1;
        while (j < n)
        {
            if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
                j++;
     
            if (a[j] >= temp)
                break;
     
            swap(a,i,j);   //与左右孩子中最小的交换,下沉
    
            i = j;            //继续向下调整堆
            j = 2 * i + 1;
        }
    
    }
    
    

    堆的初始化

    有了堆的插入和删除后,再考虑下如何对一个数据进行堆化操作。
    从最后一个非叶子结点,直至根节点,自底向上,对以这些节点为根节点的子树逐渐执行元素下沉操作。

    //建立最小堆
    void MakeMinHeap(int[] a, int n)
    {
        for (int i = n / 2 - 1; i >= 0; i--)
            fixdown(a, i, n);
    }
    

    堆排序的完整代码

    void minHeapSort(int[] a, int n)
    {
        makeMinHeap(a,n);
        for (int i = n - 1; i >= 1; i--)
        {
            swap(a[i], a[0]);
            fixdown(a, 0, i);
        }
    }
    
    void makeMinHeap(int[] a, int n)
    {
        for (int i = n / 2 - 1; i >= 0; i--)
            fixdown(a, i, n);
    }
    
    void fixdown(int[] a, int i, int n)
    {
        int j, temp;
     
        temp = a[i];
        j = 2 * i + 1;
        while (j < n)
        {
            if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
                j++;
     
            if (a[j] >= temp)
                break;
     
            swap(a,i,j);   //与左右孩子中最小的交换,下沉
    
            i = j;            //继续向下调整堆
            j = 2 * i + 1;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:堆的相关操作与堆排序

          本文链接:https://www.haomeiwen.com/subject/ukkkpqtx.html