/*
 * heapsort.cpp
 *
 *  Created on: 2016年3月30日
 *      Author: Lv_Lang
 */

//堆排序
#include <iostream>
using namespace std;

/*堆排序算法解析:
核心思想在于建立最大堆(或最小堆),
因为最大堆满足一个性质:所有的父节点都要比它的左右节点均要大,
于是据此可以每次将最大的(根节点)抽取出来(实际上是放最后面),
每次都抽取剩余部分的最大值,那最终得到的序列就是有序的。
所以堆排序其实算是一种高级版的选择排序。
建立最大堆的方法:首先从底层的父节点开始,把它的子树整成最大堆,
然后往上整成最大堆,注意这里要从下往上。
最后堆排序就是先建立一个最大堆,然后把根节点元素也就是最大的元素
跟最后面的元素交换,这样一来,树就未必满足最大堆了,所以要重新
进行堆的调整(不包括已经被抽取的最大元素)。这样下来,每次都抽取
出子序列的最大元素,最终的序列就从小到大排好序了。*/

void swap(int a[],int i,int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}

void HeapAdjust(int *a,int i,int size)
{
	int left = 2*i;//左孩子节点
	int right = 2*i + 1;//右孩子节点
	int max = i;//暂存最大元素下标
	if(left <= size && a[left] > a[max])
		//这里不直接交换是因为如果交换则要进行递归,
		//所以连同右边的也判断了再做可能的交换和做可能的递归,
		//递归的原因则是因为你把人的老爸交换了,
		//那人家的儿子可能就比继父要大了。
		//swap(a,left,i);
		max = left;
	if(right <= size && a[right] > a[max])
		max = right;
	if(max != i)//表明当前的父节点并不是最大的
	{
		swap(a,i,max);
		HeapAdjust(a,max,size);//有交换就要递归把子树也整成最大堆
	}
}

void BuildHeap(int a[],int size)
{
	for(int i = size / 2;i >= 1;i--)//非叶节点最大下标为/2
	{
		HeapAdjust(a,i,size);
	}
}

//堆排序对要排序的序列有个要求就是下标是从1开始到size的,而并非常用的0~size-1
void HeapSort(int a[],int size)
{
	BuildHeap(a,size);//先建立初始的最大堆
	for(int i = size;i >= 2;i--)
	{
		swap(a,1,i);//把最大的元素放到最后面
		size--;//不再包括最大的元素
		//这里之所以直接从根节点开始维护堆是因为除了根节点外的其他子树都是最大堆了。
		//而上面第一次建立最大堆时不能保证父节点已经是最大的了,
		//所以上面的需要先从底层的非叶节点层开始维护/调整堆。
		HeapAdjust(a,1,size);
	}
	//至此数组就已经从小到大排好序了,
	//如果要从大到小输出,则倒着输出就行了;
	//而如果要将序列从大到小排序,则应建立最小堆。
}

void print(int a[],int size)
{
	for(int i=1;i < size;i++)
		cout<<a[i]<<" ";
	cout<<a[size]<<endl;
}

int main()
{
	int a[7] = {0,4,6,1,5,3,2};
	cout<<"排序之前的序列为:"<<endl;
	print(a,6);
	HeapSort(a,6);
	cout<<"排序之后的序列为:"<<endl;
	print(a,6);

	return 0;
}

关于堆排序算法,网上有更好更详细的解析,这里放一个我觉得挺好的解析博客,因为它有图:

点击打开链接

堆排序C++实现的更多相关文章

  1. 算法与数据结构(十四) 堆排序 (Swift 3.0版)

    上篇博客主要讲了冒泡排序.插入排序.希尔排序以及选择排序.本篇博客就来讲一下堆排序(Heap Sort).看到堆排序这个名字我们就应该知道这种排序方式的特点,就是利用堆来讲我们的序列进行排序.&quo ...

  2. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...

  3. 堆排序与优先队列——算法导论(7)

    1. 预备知识 (1) 基本概念     如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...

  4. 数据结构:堆排序 (python版) 小顶堆实现从大到小排序 | 大顶堆实现从小到大排序

    #!/usr/bin/env python # -*- coding:utf-8 -*- ''' Author: Minion-Xu 小堆序实现从大到小排序,大堆序实现从小到大排序 重点的地方:小堆序 ...

  5. 堆排序(python实现)

    堆排序是利用最大最或最小堆,废话不多说: 先给出几个概念: 二叉树:二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树” 完全二叉树:除最后一层外, ...

  6. 堆排序分析及php实现

    堆排序:是一种特殊形式的选择排序,他是简单选择排序的一种改进. 什么是堆? 具有n个元素的序列:{k1,k2,ki,…,kn} (ki <= k2i,ki <= k2i+1) 或者 (ki ...

  7. 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)

    如果你觉得我的有些话有点唐突,你不理解可以想看看前一篇<C++之冒泡排序.希尔排序.快速排序.插入排序.堆排序.基数排序性能对比分析>. 这几天闲着没事就写了一篇<C++之冒泡排序. ...

  8. [Unity][Heap sort]用Unity动态演示堆排序的过程(How Heap Sort Works)

    [Unity][Heap sort]用Unity动态演示堆排序的过程 How Heap Sort Works 最近做了一个用Unity3D动态演示堆排序过程的程序. I've made this ap ...

  9. PHP实现堆排序

    经验 工作了,面试我工作这家公司时被技术面打击得不行,因为自己的数据结构等基础学得实在太差,虽然原来是想做设计师的说...不过看在PHP写得还凑合的份上能来实习了,但还是决心恶补一下基础. 其实自己之 ...

  10. 堆排序 Heapsort

    Prime + Heap 简直神了 时间优化好多,顺便就把Heapsort给撸了一发 具体看图 Heapsort利用完全二叉树+大(小)顶锥的结构每次将锥定元素和锥最末尾的元素交换 同时大(小)顶锥元 ...

随机推荐

  1. js中对象 类 实例的区别 数据类型 创建对象

    类是对象的具体细分,实例是类中的一个具体事物. 基本数据类型和 引用数据类型 基本数据类型:numble string undefined null 引用数据类型:对象和函数 对象数据类型又细分为:对 ...

  2. c#数据绑定(5)--LINQ

    嶽永鹏/文 本实例以MS AdventureWorks2008Entities数据库为基础,演示了LINQ TO ENTITY.LINQ TO ENTITYSQL和LINQ TO ENTITYCLIE ...

  3. git代码冲突解决

    1.git fetch 跟git pull差别是前者不会和本地直接merge code,而后者会,所以git fetch更安全   git fetch origin master:tmpgit dif ...

  4. java通过文件路径读取该路径下的所有文件并将其放入list中

    java通过文件路径读取该路径下的所有文件并将其放入list中   java中可以通过递归的方式获取指定路径下的所有文件并将其放入List集合中.假设指定路径为path,目标集合为fileList,遍 ...

  5. 切换jdk版本

    切换JDK 开发中jdk版本需要是1.3.1,当前电脑中用的是jdk1.8 下载jdk1.3.1 可以在官网上下,但是我捣鼓半天,发现下载又慢又需要账号,所以在CSDN下了个 地址,可以下载第一个ex ...

  6. 深入Docker

    深入Docker 作者:ramanallamilli 随着持续交付等新型开发方法的兴起,工程师再也不会凡事靠运气,希望提交代码上去后,它能在未知环境正常运行.我们可以看到业界这样的转变——开发,质量保 ...

  7. [原创]C#应用WindowsApi实现查找(FindWindowEx)文本框(TextBox、TextEdit)。

    /// <summary> /// 获取文本框控件 /// </summary> /// <param name="hwnd">文本框所在父窗口 ...

  8. Decorate Pattern 装饰者模式

    装饰模式的定义: 动态地将责任附加到对象向,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案. 遵循的设计原则是开闭原则,也是对扩展开放,对修改关闭. 下面是类图 示例代码 /** *定义被装饰者 ...

  9. 深入了解Struts2返回JSON数据的原理

    首先来看一下JSON官方对于"JSON"的解释: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析 ...

  10. 面试复习(C++)之直接插入排序

    #include <iostream> using namespace std; void Insertsort(int *a,int len) { ;j<len;j++) { in ...