排序算法 -- 堆排序

一.  堆排序

       1.  堆:类似于完全二叉树,有a1,a2,a3, ...  an,个元素,且第 2*i+1 和 2*i+2 位置的关键字都小于或大于第 i 位置的关键字。

       2.  大根堆与小根堆

            大根堆:堆中的所有元素都满足第 2*i+1 和 2*i+2 位置的关键字都小于第 i 位置的关键字。

            小根堆:堆中的所有元素都满足第 2*i+1 和 2*i+2 位置的关键字都大于第 i 位置的关键字。

       3.  堆排序:利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

二.  原理

       1.  用大根堆排序的基本思想

               ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
               ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
               ③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
               ……
               直到无序区只有一个元素为止。
        2.  例如:对数据进行排列如下图:

三.  代码实现 -- 大根堆排序

#include
  
  
   
   

using namespace std;

//一次堆调整 -- 大根堆

static heap(int* arr, int start, int end)
{
    int parent = start;
    int tmp = arr[parent];
    for(int i=parent*2+1; i<=end; i=i*2+1)
    {
        if(i+1 <= end && arr[i] < arr[i+1])
        {
            i++;
        }
        if(tmp < arr[i])
        {
            arr[parent] = arr[i];
            parent = i;
        }
        else
        {
            break;
        }
    }
    arr[parent] = tmp;
}

//堆排序 -- 大根堆

void heapSort(int* arr, int len)
{
    if(arr == NULL || len <= 0)
    {
        return;
    }
    //建立大根堆
    for(int i=(len-1-1)/2; i>=0; i--)
    {
        heap(arr,i,len-1);
    }
    //一次堆调整
    for(int i=0; i<len-1; i++)
    {
        int tmp = arr[0];
        arr[0] = arr[len-1-i];
        arr[len-1-i] = tmp;
        heap(arr,0,len-1-1-i);
    }
}
  
  

四.  时间复杂度和空间复杂度及稳定性

       1.  时间复杂度

            首先建立大根堆时,需要从(len-1-1)/2处不断调整,整个是线性的过程时间复杂度为O(n),然后对len-1个数据进行一次堆调整,直至无序区只剩下一个数据,这个过程的时间复杂度为O((n-1)*lgn),所以整个排序过程总的算下来为O(n*lgn)。

       2.  空间复杂度

            纵观整个排序过程除了局部临时变量外,未借用其它额外的空间,所以空间复杂度为O(1)。

       3.  稳定性

            无论是代码还是例图我们都可以看出,堆排序过程中是2*i+1 或 2*i+2 位置的关键字与 i 处的进行交换,这种跳跃式的数据交换使得此排序不稳定。


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值