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

    二叉堆的本质是完全二叉树

    大顶堆:每个节点的值都大于他的子节点

    小顶堆:每个节点的值都小于他的子节点

    二叉堆的根节点就是他的堆顶

    堆的存储结构

    虽然堆的数据结构是树,但是它并不是以链式结构存储的,而是顺序存储(数组)

    通过数组下标可以定位父亲节点或者孩子节点,堆中的最后一个父亲节点就是(数组长度-1)/2,已知父亲节点的下标是n,那么孩子节点的下标就是2n+1和2n+2

    堆排序的时间复杂度是O(nlogn)

    堆排序思路

    1.从下往上,找父亲节点,先找到堆中的最后一个父亲节点(ArrLen-1)/2,然后对他和他的叶子节点进行排序,方法如下:

      求出两个叶子节点下标,判断两个叶子节点是否在数组范围内,然后挨个比对;

      首先用父节点跟左孩子对比,如果父节点的值小于左孩子,那么最大值的下标就变成左孩子的下标,否则最大值下标就是父节点下标;

      用右节点的值和最大值下标对应的节点进行对比,如果右节点更大,最大下标就变为右节点的下标,否则不变;

      判断:如果最大节点下标不是父节点下标,说明父节点和他的子节点需要重新排序,父节点要和他的左孩子或者右孩子交换顺序,通过最大节点下标将父子节点中的值对换;

      此时,最大值下标就表示换过位的子节点的位置,递归调用,以这个子节点为新的父节点,进行排序,此为一次循环。

    2.之前找到的是堆中的最后一给父节点,因此需要向前遍历,将堆中的所有父节点进行排序。所作的操作就是:从(ArrLen-1)/2开始,向前遍历,每次遍历都进行排序操作,直到最终排到堆顶。

    堆排序代码

    #include<iostream>
    
    using namespace std;
    
    void BuildHeap(int ArrLen,int* Array);
    void MaxHeapify(int ArrLen,int* Array,int Index);
    
    int main(void)
    {
        int* Array;
        int ArrLen;
        cin >> ArrLen;
        Array = new int[ArrLen];
        
        for (int i = 0; i < ArrLen; ++i)
            cin >> Array[i];
    
        BuildHeap(ArrLen, Array);
    
        for (int i = 0; i < ArrLen; ++i)
            cout << Array[i] << " ";
    
        system("pause");
        return 0;
    }
    
    void BuildHeap(int ArrLen,int* Array)
    {
        // 从最后一个节点的父节点往上调整
        for (int i = (ArrLen-1)/2; i >=0; --i)
            MaxHeapify(ArrLen,Array,i);
    }
    
    void MaxHeapify(int ArrLen,int* Array,int Index)
    {
        //cout << "Array Index" << Index << endl;
    
        int Left = Index * 2 + 1;
        int Right = Index * 2 + 2;
        int MaxIndex,Temp;
    
        if (Left < ArrLen&&Array[Index] < Array[Left])
        {
            MaxIndex = Left;
        }
        else
            MaxIndex = Index;
    
        if (Right < ArrLen&&Array[MaxIndex] < Array[Right])
            MaxIndex = Right;
        //cout << "Max Index" << MaxIndex << endl;
        if (MaxIndex != Index)
        {
            Temp = Array[Index];
            Array[Index] = Array[MaxIndex];
            Array[MaxIndex] = Temp;
            MaxHeapify(ArrLen, Array, MaxIndex);
        }
    
    }

    拓展:

    求数组中第K大的数

    1.使用堆排序来做就是在一次堆排序中,将最大值排到堆顶,然后将堆顶与堆底调换位置(数组的第一个元素和最后一个元素交换位置)

    2.再进行堆排序,不理最后一个数(就是冒出来的堆顶),堆排序的长度缩减为原来的ArrLen-1(这样最后一个元素就不参与堆排序了)

    3.循环执行k次,即可得到第k大的数

    #include<iostream>
    
    using namespace std;
    
    void BuildHeap(int ArrLen,int* Array);
    void MaxHeapify(int ArrLen,int* Array,int Index);
    int KLargest(int ArrLen, int* Array, int K);
    
    int main(void)
    {
        int* Array;
        int ArrLen;
        cin >> ArrLen;
        Array = new int[ArrLen];
        
        for (int i = 0; i < ArrLen; ++i)
            cin >> Array[i];
    
        BuildHeap(ArrLen, Array);
    
        /*for (int i = 0; i < ArrLen; ++i)
            cout << Array[i] << " ";*/
    
        int K;
        cin >> K;
        cout << KLargest(ArrLen, Array, K);
    
        system("pause");
        return 0;
    }
    
    int KLargest(int ArrLen, int* Array, int K)
    {
        int PopValue;
        for (int i = 0; i < K; ++i)
        {
            BuildHeap(ArrLen + 1 - K, Array);
            for (int j = 0; j < ArrLen; ++j)
                cout << Array[j] << " ";
            cout << endl;
    
            PopValue = Array[0];
            int Temp;
            Temp = Array[ArrLen - i-1];
            Array[ArrLen - i-1] = Array[0];
            Array[0] = Temp;
    
            for (int j = 0; j < ArrLen; ++j)
                cout << Array[j] << " ";
            cout << endl;
    
        }
        return PopValue;
    }
    
    
    void BuildHeap(int ArrLen,int* Array)
    {
        // 从最后一个节点的父节点往上调整
        for (int i = (ArrLen-1)/2; i >=0; --i)
            MaxHeapify(ArrLen,Array,i);
    }
    
    void MaxHeapify(int ArrLen,int* Array,int Index)
    {
        //cout << "Array Index" << Index << endl;
    
        int Left = Index * 2 + 1;
        int Right = Index * 2 + 2;
        int MaxIndex,Temp;
    
        if (Left < ArrLen&&Array[Index] < Array[Left])
        {
            MaxIndex = Left;
        }
        else
            MaxIndex = Index;
    
        if (Right < ArrLen&&Array[MaxIndex] < Array[Right])
            MaxIndex = Right;
        //cout << "Max Index" << MaxIndex << endl;
        if (MaxIndex != Index)
        {
            Temp = Array[Index];
            Array[Index] = Array[MaxIndex];
            Array[MaxIndex] = Temp;
            MaxHeapify(ArrLen, Array, MaxIndex);
        }
    
    }
  • 相关阅读:
    FastDfs
    git入门大全
    Dynamic Compilation and Loading of .NET Objects
    ASP.NET MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合
    Windows系统不同磁盘间的扩容教程
    服务器Windows 2008 R2 安装SQL 2008 R2
    Windows实现内网IPMI端口转发
    FreeBSD 安装过程
    linux安装Zabbix监控
    Linux VPS实用简单安全配置
  • 原文地址:https://www.cnblogs.com/wangtianning1223/p/13783224.html
Copyright © 2011-2022 走看看