在面对大数据量的排序时(100W以上量级数据),通常用以下三种的排序方法效率最高O(nlogn):快速排序、归并排序,堆排序。在这个量级上,其他冒泡,选择,插入等简单排序已经无法胜任,效率极低,跟前面三种排序差了千百倍,因此不作比较。

这三种排序的平均时间复杂度均为O(nlogn),快速排序,归并排序在面对基本有序序列排序时,效率反会降低。且归并排序需要用到O(n)的临时存储空间。而堆排序没有明显缺点,特别在面对经常会插入新元素的排序需求,堆排序效果最好。

下面是三种排序对100W个无序数组进行排序的时间对比,可以看出在平均情况下,时间效率:快排>归并>堆排序

基础概念                                                                                                                                                                                                       

什么是堆?

:一种数据结构,全称为:二叉堆数据结构,是一种数组对象。

当所有节点都大于各自左右子节点时,叫大顶堆;

当所有节点都小于各自左右子节点时,叫小顶堆。

在堆排序中,使用大顶堆结构。

排序原理                                                                                                                                                                                                       

若输出堆顶的最大值之后,使得剩余n-1个元素的序列重新又建成一个堆,则得到n个元素中个次大值。如此反复执行,便能得到一个有序序列,这个过程就称之为堆排序。

因此堆排序的实现思路,可以细分为两部分:

1、如何将一个无序数组排列成大顶堆(建堆过程)

2、拿走最大值后如何从剩下的堆中找出次大值,重新建立大顶堆(筛选过程)

时间复杂度                                                                                                                                                                                                    

堆排序可分细分为两部分:建堆过程+排序过程。

建堆过程时间复杂度为O(n),即将一个无序数组建立成堆只需要线性时间。

排序过程需要对n个数据进行筛选时,每次筛选需要O(logn)时间,所以整个排序过程的时间为O(nlogn)

因此堆排序总的运行时间为: O(nlogn) = O(n) + O(nlogn)

算法实现                                                                                                                                                                                                        

#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std; int a[]; #define BEGIN_RECORD \
{ \
clock_t ____temp_begin_time___; \
____temp_begin_time___=clock(); #define END_RECORD(dtime) \
dtime=float(clock()-____temp_begin_time___)/CLOCKS_PER_SEC;\
} /*
目标:筛选区域为以索引i为树根的子树,找出该子树最大值,将其存放到索引i
过程:从索引为i的结点开始往下,与较大的子节点交换值,向下搜索直到子树底部
a - 待排序数组
i - 筛选起始结点索引
len - 排序元素数量
*/
void sift(int a[], int i, int len)
{
int temp = a[i];
int j = * i; while(j <= len)
{
if(j < len && a[j] < a[j+]) //如果右结点比左结点大,则拿右结点跟父节点比较
j++;
if(a[i] < a[j]) //如果子节点比父节点大,则两者交换值,子节点成为新的父节点,继续向下筛选
{
a[i] = a[j];
a[j] = temp;
i = j;
j = * i;
}
else //如果父节点比子节点大,则说明找到了该子树的最大值,结束筛选
{
break;
}
}
a[i] = temp;
} /*
堆排序(大顶堆)
a - 待排序的数组
len - 数组长度
*/
void heapSort(int a[], int len)
{
int temp;
int i; for (i = len-; i > ; i--) //堆排序只能从下标为1开始排序,因此要把数组所有数据后一移位。下标0的数据不处理
{
a[i] = a[i - ];
} for (i = len/; i >= ; i--) //建堆过程(使得全树的父节点都比子节点大)
{
sift(a, i, len);
}
for (i = len - ; i >= ; i--) //排序过程:每次从树根取值(该值必为最大值),放到树的最后一个结点n,并把该结点从树中移除。重复排序过程,直到将所有结点从树移除,排序结束
{
temp = a[];
a[] = a[i];
a[i] = temp;
sift(a, , i - ); //从树根取出最大值,取最尾树结点放到树根,此时树根不再为最大值,需要再对树根进行一次筛选过程,以确保树根仍然为最大值
}
} void printArray(int a[], int length)
{
cout << "数组内容:";
for(int i = ; i < length; i++)
{
if(i == )
cout << a[i];
else
cout << "," << a[i]; }
cout << endl;
} int _tmain(int argc, _TCHAR* argv[])
{
float tim;
BEGIN_RECORD //int a[1000000];
for (int i = ; i < ; i++)
{
a[i] = int(rand() % );
} //printArray(a, sizeof(a)/sizeof(int));
heapSort(a, sizeof(a)/sizeof(int));
//printArray(a, sizeof(a)/sizeof(int)); END_RECORD(tim) cout << "运行时间:" << tim << "s" << endl; system("pause");
return ;
}

处理海量数据的高级排序之——堆排序(C++)的更多相关文章

  1. 处理海量数据的高级排序之——希尔排序(C++)

    希尔算法简介                                                                                              ...

  2. 处理海量数据的高级排序之——归并排序(C++)

    代码实现                                                                                                 ...

  3. 处理海量数据的高级排序之——快速排序(C++)

    代码实现                                                                                                 ...

  4. javascript数据结构与算法--高级排序算法

    javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...

  5. IOS- 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序

    /*******************************快速排序 start**********************************///随即取 当前取第一个,首先找到第一个的位置 ...

  6. 数据结构和算法 – 11.高级排序算法(上)

      对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种:       交换排序: 包括冒泡排序,快速排序.       选择排序: 包括直接选择排序,堆排序.       插入排序 ...

  7. 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)

    解题思路: 排序方法:多路归并排序 每次将n个list的头元素取出来,进行排序(堆排序),最小元素从堆中取出后,将其所在list的下一个元素 放入堆中,调整堆序列. 函数实现原型: void list ...

  8. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  9. Java数据结构和算法 - 高级排序

    希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...

随机推荐

  1. hdu 4046 2011北京赛区网络赛G 线段树 ***

    还带这么做的,卧槽,15分钟就被A了的题,居然没搞出来 若某位是1,则前两个为wb,这位就是w #include<cstdio> #include<cstring> #defi ...

  2. 再谈EF Core内存数据库单元测试问题

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:在用EF Core的内存数据库进行单元测试的时候遇到"无法访问已释放的对象& ...

  3. 第一次尝试用 Live Writer 写博客

    之前在官网上下载了最新版的Windows Live Writer,可是安装不了,就在其他网站下了一个试试,可以安装,不过却是2009年的版本,很不喜欢,我希望能体验最新版的,回头还得重新下个最新版的安 ...

  4. Unity3D打Box游戏

    先学习一些基本的脚本实现: 1.动态创建物体.默认位置是(0,0)位置 GameObject goNew = GameObject.CreatePrimitive(PrimitiveType.Cube ...

  5. ML 06、感知机

    机器学习算法 原理.实现与实践  —— 感知机 感知机(perceptron)是二分类的线性分类模型,输入为特征向量,输出为实例的类别,取值+1和-1.感知机学习旨在求出将训练数据进行线性划分的分离超 ...

  6. document.body / document.ducumentElement /等获取高度和宽度的区别 ----转载

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. 原生JavaScript 全特效微博发布面板效果实现

    javaScript实现微博发布面板效果.---转载白超华 采用的js知识有: 正则表达式区分中英文字节.随机数生成等函数 淡入淡出.缓冲运动.闪动等动画函数 onfocus.onblur.oninp ...

  8. ADB常用的几个命令

    1. 查看设备 adb devices 查看当前连接的设备, 连接到计算机的android设备或者模拟器将会列出显示 2. 安装软件 adb install [-r] [-s] <file> ...

  9. MySql 的数据储存引擎

    1.存储引擎是什么? Mysql中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术, ...

  10. HTML5(常用的表单控件)

    常用的HTML5的表单控件: Input 类型: color color 类型用在input字段主要用于选取颜色,如下所示: 从拾色器中选择一个颜色: 选择你喜欢的颜色: <input type ...