排序算法——堆排序
2014-04-15 10:55
183 查看
前一阵子一直在写排序的系列文章,最近因为一些事情耽搁了几天,也穿插了几篇其他类别的随笔。今天还是回到排序上面来,善始善终,呵呵。
今天要介绍的也是一种效率很高的排序——堆排序
思想
堆排序,顾名思义,就是基于堆。因此先来介绍一下堆的概念。
堆分为最大堆和最小堆,其实就是完全二叉树。最大堆要求节点的元素都要大于其孩子,最小堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求,其实很好理解。有了上面的定义,我们可以得知,处于最大堆的根节点的元素一定是这个堆中的最大值。其实我们的堆排序算法就是抓住了堆的这一特点,每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最大堆,依次类推,最终得到排序的序列。
或者说,堆排序将所有的待排序数据分为两部分,无序区和有序区。无序区也就是前面的最大堆数据,有序区是每次将堆顶元素放到最后排列而成的序列。每一次堆排序过程都是有序区元素个数增加,无序区元素个数减少的过程。当无序区元素个数为1时,堆排序就完成了。
本质上讲,堆排序是一种选择排序,每次都选择堆中最大的元素进行排序。只不过堆排序选择元素的方法更为先进,时间复杂度更低,效率更高。
图例说明一下:(图片来自http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html)
具体步骤如下:
1
首先从第一个非叶子节点开始,比较当前节点和其孩子节点,将最大的元素放在当前节点,交换当前节点和最大节点元素。
2
将当前元素前面所有的元素都进行1的过程,这样就生成了最大堆
3
将堆顶元素和最后一个元素交换,列表长度减1。由此无序区减1,有序区加1
4
剩余元素重新调整建堆
5
继续3和4,直到所有元素都完成排序
代码
int adjust_heap(vector<int> &v,
int length,
int i){
intleft =
2 * i;
int right =
2 * i+
1;
intlargest = i;
inttemp;
while(left< length || right < length){
if(left < length && v[largest] < v[left]){
largest = left;
}
if (right< length && v[largest] < v[right]){
largest = right;
}
if (i!= largest){
temp =v[largest];
v[largest] =v[i];
v[i] = temp;
i = largest;
left = 2 * i;
right = 2 * i +
1;
}
else{
break;
}
}
}
int build_heap(vector<int>&v,
int length){
int i;
intbegin = length/2 -
1; //get the last parent node
for (i = begin; i>=0;i--){
adjust_heap(v,length,i);
}
}
int heap_sort(vector<int>&v){
intlength = v.size();
int temp;
printline("before sort:",v);
build_heap(v,length);
while(length>
1){
temp = v[length-1];
v[length-1] = v[0];
v[0] = temp;
length--;
adjust_heap(v,length,0);
}
printline("after sort:",v);
}
分析
堆排序的平均时间复杂度为O(nlogn),接近于最坏的时间复杂度。在最好情况下,时间复杂度为O(1).
今天要介绍的也是一种效率很高的排序——堆排序
思想
堆排序,顾名思义,就是基于堆。因此先来介绍一下堆的概念。
堆分为最大堆和最小堆,其实就是完全二叉树。最大堆要求节点的元素都要大于其孩子,最小堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求,其实很好理解。有了上面的定义,我们可以得知,处于最大堆的根节点的元素一定是这个堆中的最大值。其实我们的堆排序算法就是抓住了堆的这一特点,每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最大堆,依次类推,最终得到排序的序列。
或者说,堆排序将所有的待排序数据分为两部分,无序区和有序区。无序区也就是前面的最大堆数据,有序区是每次将堆顶元素放到最后排列而成的序列。每一次堆排序过程都是有序区元素个数增加,无序区元素个数减少的过程。当无序区元素个数为1时,堆排序就完成了。
本质上讲,堆排序是一种选择排序,每次都选择堆中最大的元素进行排序。只不过堆排序选择元素的方法更为先进,时间复杂度更低,效率更高。
图例说明一下:(图片来自http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html)
具体步骤如下:
1
首先从第一个非叶子节点开始,比较当前节点和其孩子节点,将最大的元素放在当前节点,交换当前节点和最大节点元素。
2
将当前元素前面所有的元素都进行1的过程,这样就生成了最大堆
3
将堆顶元素和最后一个元素交换,列表长度减1。由此无序区减1,有序区加1
4
剩余元素重新调整建堆
5
继续3和4,直到所有元素都完成排序
代码
int adjust_heap(vector<int> &v,
int length,
int i){
intleft =
2 * i;
int right =
2 * i+
1;
intlargest = i;
inttemp;
while(left< length || right < length){
if(left < length && v[largest] < v[left]){
largest = left;
}
if (right< length && v[largest] < v[right]){
largest = right;
}
if (i!= largest){
temp =v[largest];
v[largest] =v[i];
v[i] = temp;
i = largest;
left = 2 * i;
right = 2 * i +
1;
}
else{
break;
}
}
}
int build_heap(vector<int>&v,
int length){
int i;
intbegin = length/2 -
1; //get the last parent node
for (i = begin; i>=0;i--){
adjust_heap(v,length,i);
}
}
int heap_sort(vector<int>&v){
intlength = v.size();
int temp;
printline("before sort:",v);
build_heap(v,length);
while(length>
1){
temp = v[length-1];
v[length-1] = v[0];
v[0] = temp;
length--;
adjust_heap(v,length,0);
}
printline("after sort:",v);
}
分析
堆排序的平均时间复杂度为O(nlogn),接近于最坏的时间复杂度。在最好情况下,时间复杂度为O(1).
相关文章推荐
- Android 邮件自适应问题
- Android菜鸟的成长笔记(8)——Intent与Intent Filter(上)
- springmvc请求接收参数的几种方法
- ExcelHelp 学习笔记二: C# 往Excel中写入数据
- Jquery复选框
- DRILLNET 2.0------第二十四章 井涌模拟分析模型
- android ListView的背景美化
- MySQL 可以用localhost 连接,但不能用IP连接的问题 (from:internet)
- Android - Binder机制 - ProcessState和IPCThreadState
- struct和union的区别
- javascript字符串处理
- Error 40000: Object (" ") did not match the required type `Hash'
- hasLayout
- ssh2通用分页
- 给网站添加favicon.ico
- NYOJ--重建二叉树
- 三种常用的查找算法:顺序查找法、二分法、二叉树
- 处理问题的思维模式
- hadoop命令
- SQL语句---nvl 用法