body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

堆排序(Heap Sort):是对简单选择排序进行的一种改进,是Floyd和William在1964年共同发明的。简单选择排序每次选择一个数所做中间比较结果没有保存下来,整个排序分配n-1趟遍历比较,每次只能确定一个数,这个过程中重复执行了多次比较操作。堆排序的目的就是把一趟比较中的中间结果也保存下来。
堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大根堆。或者每个结点的值都小于或等于其左右孩子结点的值,称为小跟堆。
堆排序(Heap Sort):将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值。如此反复,就能得到一个有序序列了。
对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 
堆排序基本思想:
a.将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
#include<iostream>
using namespace std;
int headSort(int* arr,int length);
void adjust(int* arr,int idx1,int idx2);
void swap(int& a,int& b);
int main()
{
        int arr[9] = {50,10,90,30,70,40,80,60,20};
        for(int idx=0;idx!=9;++idx)
                cout<<arr[idx]<<" ";
        cout<<endl;
        headSort(arr,9);
        for(int idx=0;idx!=9;++idx)
                cout<<arr[idx]<<" ";
        cout<<endl;
        system("pause");
}
void swap(int& a,int& b)
{
        int tmp = a;
        a = b;
        b = tmp;
}
//堆排序,数组下标对应其在堆数据结构中的结点位置,从0开始编号,堆是完全二叉树
int headSort(int* arr,int length)
{
        if(nullptr==arr||length<=0)
                return -1;
        //数组中顺序存放的数据就对应完全二叉树堆中的对应结点的值,现在调整为大根堆
        for(int idx=length/2-1;idx>=0;--idx)  //从最后一个非叶子结点开始调整为最大堆
        {
                adjust(arr,idx,length-1);  //最后一个非叶子结点和它的孩子比较调整
        }
        //排序,根结点后最后一个结点交换,调整
        for(int idx=length-1;idx>0;--idx)
        {
                swap(arr[0],arr[idx]);  //每次选出一个最大的数放到末尾,也就是数组末尾
                adjust(arr,0,idx-1);  //调整根结点到idx-1个结点为大根堆
        }
        return 0;
}
void adjust(int* arr,int idx1,int idx2)
{
        if(nullptr==arr||idx1>=idx2||idx1<0||idx2<0)
                return ;
        int tmp = arr[idx1];  //暂时存放要调整的数据
        for(int idx=idx1*2+1;idx<=idx2;idx=idx*2+1)  //从要调整的数据的左孩子开始比较
        {
                //选出左右孩子中的最大结点
                if(idx+1<=idx2 && arr[idx]<arr[idx+1])
                        ++idx;
                if(arr[idx]>tmp)  //不满足大根堆,调整
                {
                        arr[idx1] = arr[idx];  //交换,可能破坏子树满足大根堆的性质
                        idx1 = idx;  //本来这里要交换的,但时tmp暂时存放了初始arr[idx1]的值,这里每次比较都是和tmp比较,好比交换了,所以可以不用先交换
                        //继续向下调整,直到树满足大根堆性质
                }
                else
                        break;
        }
        arr[idx1] = tmp;
}

堆排序,图解,C/C++实现的更多相关文章

  1. 七种常见经典排序算法总结(C++)

    最近想复习下C++,很久没怎么用了,毕业时的一些经典排序算法也忘差不多了,所以刚好一起再学习一遍. 除了冒泡.插入.选择这几个复杂度O(n^2)的基本排序算法,希尔.归并.快速.堆排序,多多少少还有些 ...

  2. leetcode 排序问题

    1.堆排序 //大顶堆的构造,传入的i是父节点 void HeapAdjust(int k[],int p,int n) { int i,temp; temp = k[p]; * p; i <= ...

  3. 找工作面试题记录与参考资料(Golang/C++/计算机网络/操作系统/算法等)

    记录下去年(2020年)找工作的面试题及参考资料. C++ 智能指针的实现原理 多态的实现原理[2] C++11/14/17新特性[3] 手写memcpy和memmove[4] 介绍下boost库 计 ...

  4. 排序图解:js排序算法实现

    之前写过js实现数组去重, 今天继续研究数组: 排序算法实现. 排序是数据结构主要内容,并不限于语言主要在于思想:大学曾经用C语言研究过一段时间的排序实现, 这段时间有空用JS再将排序知识点熟悉一遍. ...

  5. 堆排序HeapSort

    堆排序,顾名思义,是采用数据结构堆来进行排序的一种排序算法. 研究没有规律的堆,没有任何意义.特殊的堆有最大堆(父节点值大于等于左右字节点值),最小堆(父节点值小于等于子节点值).一般采用最大堆来进行 ...

  6. 数据结构与算法之PHP排序算法(堆排序)

    一.堆的定义 堆通常是一个可以被看做一棵树的数组对象,其任一非叶节点满足以下性质: 1)堆中某个节点的值总是不大于或不小于其父节点的值: 每个节点的值都大于或等于其左右子节点的值,称为大顶堆.即:ar ...

  7. 堆排序(大顶堆、小顶堆)----C语言

    堆排序 之前的随笔写了栈(顺序栈.链式栈).队列(循环队列.链式队列).链表.二叉树,这次随笔来写堆 1.什么是堆? 堆是一种非线性结构,(本篇随笔主要分析堆的数组实现)可以把堆看作一个数组,也可以被 ...

  8. Python 堆与堆排序

    堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足 ...

  9. C语言堆排序

    堆是一种类似二叉树的数据结构,分为最大堆和最小堆,最大堆得定义是当前节点必须大于左右子节点,堆中所有节点都要符合这个定义.最小堆反之.这一点不同于二叉树排序.假设有数组int a[10] = {90, ...

随机推荐

  1. Asp.net core 学习笔记 ( ef core )

    更新 : 2018-11-26 这里记入一下关于 foreignKey cascade action 默认情况下如果我们使用 data annotation required + foreginkey ...

  2. uva11388

    因为a,b整除gcd(a,b),lcm(a,b)又整除a,b,因此如果lcm不整除gcd就是-1:否则的话,lcm=a*b/gcd.而a不能小于gcd,因此a就取gcd,b取lcm. #include ...

  3. p1530 Fractions to Decimals

    将余数记录下来,如果余数相同,那么商的下一位也相同. #include <iostream> #include <cstdio> #include <cmath> ...

  4. synchronized相关用法简述

    synchronized 锁,他是一个java 的关键字,能够保证同一线程只有一个线程访问或使用此修饰的代码块 用法 synchronized方法,synchronized块 synchronized ...

  5. ssd制作数据和训练

    1.在/data/VOCdevkit下建立自己的数据集名称如MyDataSet,在MyDataSet目录下需包含Annotations.ImageSets.JPEGImages三个文件夹: 2.Ima ...

  6. django 中基于类的视图

    django 视图 分为两种: 1.  FBV  基于函数的视图      function   based  view 2.  CBV  基于类的视图         class   based  ...

  7. Linux中安装Mysql授权远程访问

    一.直接授权 mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youpassword' WITH GRANT OP ...

  8. find xss

    from :http://blog.sina.com.cn/s/blog_68d342d90100nh7b.html 什么是XSS跨站攻击: http://baike.baidu.com/view/5 ...

  9. Tanya and Password CodeForces - 508D (欧拉回路)

    大意:给定n个长为3的子串, 求一个长为n+2的字符串包含所有子串. 相邻两个字符开一个节点, 建图跑欧拉回路, 若存在的话长度一定是$\le n+2$.

  10. python记录_day018 md5加密

    MD5 用法: import hashlib obj = hashlib.md5(加盐) obj.update(明文的bytes) obj.hexdigest() 获取密文 示例: import ha ...