处理海量数据的高级排序之——堆排序(C++)
在面对大数据量的排序时(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++)的更多相关文章
- 处理海量数据的高级排序之——希尔排序(C++)
希尔算法简介 ...
- 处理海量数据的高级排序之——归并排序(C++)
代码实现 ...
- 处理海量数据的高级排序之——快速排序(C++)
代码实现 ...
- javascript数据结构与算法--高级排序算法
javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...
- IOS- 快速排序,冒泡排序,直接插入排序和折半插入排序,希尔排序,堆排序,直接选择排序
/*******************************快速排序 start**********************************///随即取 当前取第一个,首先找到第一个的位置 ...
- 数据结构和算法 – 11.高级排序算法(上)
对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种: 交换排序: 包括冒泡排序,快速排序. 选择排序: 包括直接选择排序,堆排序. 插入排序 ...
- 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)
解题思路: 排序方法:多路归并排序 每次将n个list的头元素取出来,进行排序(堆排序),最小元素从堆中取出后,将其所在list的下一个元素 放入堆中,调整堆序列. 函数实现原型: void list ...
- 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...
- Java数据结构和算法 - 高级排序
希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...
随机推荐
- 【转】从RGB色转为灰度色算法
----本文摘自作者ZYL910的博客 一.基础 对于彩色转灰度,有一个很著名的心理学公式: Gray = R*0.299 + G*0.587 + B*0.114 二.整数算法 而实际应用时,希望避 ...
- MySQL数据库在WINDOWS系统CMD下的编码问题
MySQL数据库在WINDOWS系统CMD下的编码问题 1. 查看MySQL数据库编码 * SHOW VARIABLES LIKE 'char%'; 2. 编码解释 * character_set_c ...
- vmstat的使用(查看系统各种负载)
$ vmstatprocs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ r b swpd f ...
- Bootstrap Table 表格参数详解
表格参数 名称 标签 类型 默认 描述 - data-toggle String 'table' 不用写 JavaScript 直接启用表格. classes data-class ...
- python中的变量和数据类型
一.变量定义:变量是计算机内存中的一块区域,存储规定范围内的值,值 可以改变,通俗的说变量就是给数据起个名字. 二.变量命名规则: 1. 变量名由字母.数字.下划线组成 2. 数字不能开头 3. 不可 ...
- cf429B dp递推
Description Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to loo ...
- POJ 3693 后缀数组
题目链接:http://poj.org/problem?id=3693 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现在给定一个长度为n的 ...
- DSP using MATLAB 示例Example2.11
上代码: b = [1]; a = [1, -1, 0.9]; n = [-20:120]; h = impz(b,a,n); set(gcf,'Color','white'); %subplot(2 ...
- 编写css相关注意事项以及小技巧
一.小技巧 1.对于开始写网站css之前一般都要对css进行重置(养成写注释的习惯): ;;} body{font-size:16px;} img{border:none;} li{list-styl ...
- 用脚本完成mysql工作
1. 用mysql -e在脚本中执行mysql的sql语句 #!/bin/bash #simple mysql shell usage logtime=`date "+%Y-%m-%d&qu ...