简单易懂的讲堆排序
来源:互联网 发布:一键传淘宝的弊端 编辑:程序博客网 时间:2024/05/22 06:44
堆排序利用二叉堆来进行排序,而二叉堆用完全二叉树代替(因为易于储存和索引),一个数组就可以存储完全二叉树。(๑╹◡╹)ノ"""
但堆并不一定是完全二叉树,堆还有更复杂的,就不一一列举;
怎么用数组存储呢?对于每一个节点i,其父节点为i/2,其左右子节点分别为i*2,i*2+1;如图:
怎么进行排序呢,我们分为两个大步骤:
1,构建一个最大堆(每一个父节点都大于其子节点)
对于每一个非叶子节点(有叶子的节点),如果其小于子节点,那么就与子节点中较大的进行交换;
对于一个节点数为n的二叉堆来说,最后一个非叶子节点为n/2;
#include<bits/stdc++.h>using namespace std;void sift(int *r,int low,int high){int i=low,j=2*low;int tmp=r[low];while(j<=high){//如果存在左子节点 j代表左节点 if(j<high&&r[j]<r[j+1])j+=1;//如果存在右节点且右节点大于左节点 j+=1 j代表右节点 if(tmp<r[j]){ //如果较大的节点大于父节点就交换 r[i]=r[j]; //交换 i=j;j*=2; //继续判断子节点的子节点 }else break; //小于就终止 }r[i]=tmp;}int main(){int a[7]={0,5,2,4,6,1,3};//从1开始为有效,即树根编号为1; for(int i=6/2;i>=1;i--){sift(a,i,6);}for(int i=1;i<=6;i++)cout<<a[i];return 0;}输出为654213即如图:
所有的父节点都大于其子节点,最大堆构建完成;
2,从最后一个元素开始到第一个元素进行如下操作:
(1)交换当前元素与第一个元素(根据最大堆性质,第一个元素最大);
(2)然后忽视被交换到后面的元素并重构最大堆
(1)最后一个元素编号为6,值为3与第一个元素进行交换:
(2)交换一次后可以看到6已经到达了位置,即6已经排好了序;
排除6重新构建最大堆:
(1)交换倒数第二个元素和第一个元素:
第二个元素到达位置,即5,6已经排好序
(2)忽略5,6并重构最大堆。。。。。。。。
这样一直到排好序,即每一次都有一个元素排好序,每次找堆顶元素(除去已排好序的元素中最大的数)并将其放到其应该待的位置;
完整代码:
#include<bits/stdc++.h> using namespace std;void sift(int *r,int low,int high){int i=low,j=2*low;int tmp=r[low];while(j<=high){//如果存在左子节点 j代表左节点 if(j<high&&r[j]<r[j+1])j+=1;//如果存在右节点且右节点大于左节点 j+=1 j代表右节点 if(tmp<r[j]){ //如果较大的节点大于父节点就交换 r[i]=r[j]; //交换 i=j;j*=2; //继续判断子节点的子节点 }else break; //小于就终止 }r[i]=tmp;}void HeapSort(int *r,int n){int i;for(i=n/2;i>=1;i--){ //构建初始最大堆 sift(r,i,n); }for(i=n;i>=2;i--){ //进行排序的过程 swap(r[1],r[i]);//交换未排好序中最大的数到达其排好序后应在的位置; sift(r,1,i-1);// 思考一下为什么是i-1,文章最后给出解答 }} int main(){int a[7]={0,5,2,4,6,1,3};HeapSort(a,6);for(int i=1;i<=6;i++)cout<<a[i];return 0;}彩蛋:i-1即排除已经排好序的那些在末尾的大元素们,在未排序的序列中进行最大堆的重构( ̄▽ ̄)~*
阅读全文
1 0
- 简单易懂的讲堆排序
- 简单易懂堆排序
- 算法与数据结构之堆的相关知识,简单易懂。
- 简单的排序---堆排序
- 快速排序和冒泡排序【最简单易懂的Demo】
- 堆排序详讲
- 单链表排序问题、简单易懂
- Java实现对三个数字的排序----简单易懂
- JAVA对快速排序的实现,简单易懂
- 简单易懂的使用
- 简单易懂的UML
- [机器学习]线性回归 被Andrew Ng讲的如此简单易懂
- Dijkstra+堆优化模板 (手写堆简单易懂)
- 排序:简单排序-堆
- Surface、SurfaceView、View,讲的浅显易懂
- 浅显易懂的桶排序
- 简而易懂的排序
- 排序算法易懂的介绍
- C++ STL开发温习与总结(一): 1.C++编程技术
- angular+点击按钮,隐藏和显示F12打印状态
- android屏幕适配方案二(百分比布局)
- XStream(JavaBean转换为xml)
- javascript中的for in循环和for循环的使用
- 简单易懂的讲堆排序
- [洛谷 P1090]合并果子 --- 手打二叉堆
- 【分享】《遭遇美国教育》
- C语言内存分布
- BIO与NIO、AIO的区别(这个容易理解)
- BAT脚本编写教程(比较易懂和全面)
- 欢迎使用CSDN-markdown编辑器
- C#基础-049 接口
- ITASCA PFC 2D&3D DISCERETE ELEMENT MODELING