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

                                                     一 初识堆

    数据结构是一种数组,它可以视为一颗完全二叉树。如下图:

           

    图中的树是数组,A={16, 14, 10, 8, 7, 9, 3, 7},圈内表示数值,圈外红色的数字表示数组的下标。

    array_size是数组的大小(此时是8),heap_size是构建堆的元素的多少。满足heap_size<= array_size

    给定某结点的下表i,其父结点下标为PARENT(i), 左儿子下标为LEFT(i), 右儿子下标为RIGHT(i)。满足

             PARENT(i) = int((i-1)/2) ;   LEFT(i) = 2*i+1;   RIGHT(i)=2*i+2

    最大堆满足:对于任何结点(除根节点)PARENT(i) > i

    最小堆满足:对于任何结点(除根节点)PARENT(i) <i

    叶子节点(下标):int(i/2), int(i/2)+1......array_size

    下面的介绍以最大堆为例

                                                  二 保持堆的性质

           最大堆的性质为 PARENT(i) > i,因此对于特定的结点,应满足比左右儿子都大

        在上图中下标为1的结点值为2,左孩子为4,右孩子为1,1结点比左孩子小,就让1结点和3结点数值换过来。若此时4结点大于4,就把1结点和4结点数值换过来。

    参考程序:

    void MAX_HEAPIFY(int *A, int heap_size, int i)   //i 为待处理保持性质的结点下标
    {
            int l = 2 * i + 1;                       //左孩子
            int r = 2 * i + 2;                       //右孩子
            int largest = i;
            if(l < heap_size && A[largest] < A[l])   // 左孩子数值大
            {
                largest = l;
            }
         if(r < heap_size && A[largest] < A[r])   //右孩子数值大
    { largest
    = r; } if(largest != i) { int tmp = A[i]; A[i] = A[largest]; A[largest] = tmp; MAX_HEAPIFY(A, heap_size, largest); //再从数值大的结点继续往下递归处理 } }

                                                  三 构建堆

          从底向上使得每个结点保持堆的性质就可以构建堆,因为叶子节点就自己,无儿女,因此从倒数第一个非叶子节点开始依次往上构建,直到树根位置,而叶子节点开始的位置是int(i/2),因此第一个令其保持性质的结点下标为int((i-1)/2)。接着是int((i-1)/2-1)一直到0为止。下图表示了构建堆的详细过程:

    图中有9个结点,int(9/2)= 4, 从4-1=3开始(依次是4 3 2 1 0)。注意是从后往前,为何不是从前往后,显然如果是上图中,从0开始,是6和3交换,我们知道在最大堆中根是最大的,可是从前往后的话,最大值7在无出头之日。

    参考程序:

    void BUILD_MAX_HEAP(int *A, int array_size, int heap_size)
    {
            int i;
            for (i=array_size/2-1; i>=0; i--)
            {
                MAX_HEAPIFY(A, heap_size, i);
            }
    }

                                                  四 堆排序

          最大堆把最大值排到了首个位置A[0],这是如果把最大值和最后一个值A[heap_size-1]换过来,再使A[0]保持堆的性质,再使heap_size自建。重复以上过程,就是个非递减排序。下图是一个事例过程:

    参考程序:

    void HEAP_SORT(int *A, int array_size, int heap_size)
    {
            int tmp;
            BUILD_MAX_HEAP(A, array_size, heap_size);
            while(heap_size > 1)
            {
                tmp = A[0];
                A[0] = A[heap_size-1];
                A[heap_size] = tmp;
                heap_size--;
                MAX_HEAPIFY(A, heap_size, 0);
            }
    }

    测试

    #include <iostream>
    #include <vector>
    using namespace std;
    void maxHeapify(int A[], int lens, int i)
    {
        if (A == NULL || i >= lens)
            return;
        int l = 2 * i + 1;
        int r = 2 * i + 2;
        int largest = i;
        if (l < lens || A[i] > A[largest])
            largest = l;
        if (r < lens && A[r] > A[largest])
            largest = r;
        if (largest != i)
        {
            int tmp = A[largest];
            A[largest] = A[i];
            A[i] = tmp;
            maxHeapify(A, lens, largest);
        }
    }
    void buildHeap(int A[], int lens)
    {
        if (A == NULL || lens <= 0)
            return;
        int mid = (lens-2) / 2;
        for (int i = mid; i >= 0; --i)
            maxHeapify(A, lens, i);
    }
    void heapSort(int A[], int lens)
    {
        buildHeap(A, lens);
        while (lens > 1)
        {
            int tmp = A[lens-1];
            A[lens-1] = A[0];
            A[0] = tmp;
            --lens;
            maxHeapify(A, lens, 0);
        }
    }
    void tranverse(int A[], int lens)
    {
        if (A == NULL || lens <= 0)
            return;
        for (int i = 0; i < lens; ++i)
            cout << A[i] << "  ";
        cout << endl;
    }
        
    int main()
    {
        int A[] = {3, 2, 8, 7, 0, 11};
        int lens = sizeof(A) / sizeof(*A);
        tranverse(A, lens);
    //    buildHeap(A, lens);
    //    tranverse(A, lens);
        heapSort(A, lens);
        tranverse(A, lens);
    }

                                                

    五 堆操作

    1.HEAP_MAXIMUM(A) 找出最大的元素

    int  HEAP_MAXIMUM(int *A)
    {
            return A[0];
    }

    2.int HEAP_EXTRACT_MAX(int *A, int heap_size) 找出堆中最大元素,并删除,保持堆

    int HEAP_EXTRACT_MAX(int *A, int heap_size)
    {
            int max;
            max = A[0];
            A[0] = A[heap_size-1];
            heap_size--;
            MAX_HEAPIFY(A, heap_size, 0);
            
            return max;
    }

    3. void HEAP_INCREASE_KEY(int *A, int heap_size, int i, int key) 第i个位置出若key比原来大,就改成key,保持堆

    void HEAP_INCREASE_KEY(int *A, int heap_size, int i, int key)
    {
            int tmp;
            if(A[i] > key)
            {
                printf("The key is smaller than A[i]");
            }
            else
            {
                A[i] = key;
                while(i>=1 && A[(i-1)/2] < A[i])
                {
                    tmp = A[i];
                    A[i] = A[(i-1)/2];
                    A[(i-1)/2] = tmp;
                    i = (i-1)/2;
                    MAX_HEAPIFY(A, heap_size, i);
                }
            }
    
    }

    4.void MAX_HEAP_INSERT(int *A, int array_size, int heap_size, int key) 堆中插入元素

    void MAX_HEAP_INSERT(int *A, int array_size, int heap_size, int key)
    {
            array_size++;
            heap_size++;
            A[heap_size] = -32768;
            HEAP_INCREASE_KEY(A, heap_size, heap_size-1, key);
    }
  • 相关阅读:
    HD-ACM算法专攻系列(16)——考试排名
    HD-ACM算法专攻系列(15)——Quoit Design
    HD-ACM算法专攻系列(14)——find your present (2)
    HD-ACM算法专攻系列(13)——How Many Fibs?
    HD-ACM算法专攻系列(12)——Integer Inquiry
    HD-ACM算法专攻系列(11)——Exponentiation
    HD-ACM算法专攻系列(10)——大明A+B
    深入了解CI/CD:工具、方法、环境、基础架构的全面指南
    了解这5大K8S管理服务,为你节省50%的部署时间!
    如何使用Rancher在OpenStack上创建K8S集群
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/2922970.html
Copyright © 2011-2022 走看看