基本排序算法(2)

1、堆排序

      堆排序 的基本思想:充分利用了完全二叉树的深度为 log2N + 1。首先将待排序序列构造成一个大(小)顶堆。此时,堆顶的根结点就是整个序列的最大值,将根结点与最后一个结点交换(移走根节点)。然后调整,将剩余的N-1个记录重新构造成一个大(小)顶堆,此时,堆顶的根结点就是整个序列的最大值。。。。。反复执行,直到得到一个有序序列。

       转(http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html

      参考(http://blog.csdn.net/morewindows/article/details/6709644/

      参考(http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

堆的定义:

    例如,下列两个序列为堆,对应的完全二叉树如图: (若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。)

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

   堆排序(Heap Sort)只需要一个记录元素大小的辅助空间(供交换用),每个待排序的记录仅占有一个存储空间。

 

堆的存储:

  一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+12*i+2(注:如果根结点是从1开始,则左右孩子结点分别是2i和2i+1。)

  如最大化堆如下:

   

 

  左图为其存储结构,右图为其逻辑结构。

2堆排序实例

   首先,建立初始的堆结构如图:

  

  然后,交换堆顶的元素和最后一个元素,此时最后一个位置作为有序区(有序区显示为黄色),然后进行其他无序区的堆调整,重新得到大顶堆后,交换堆顶和倒数第二个元素的位置……

  

  重复此过程:

  

 

  最后,有序区扩展完成即排序完成:

  

 

  由排序过程可见,若想得到升序,则建立大顶堆,若想得到降序,则建立小顶堆


3、堆排序的实现

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<algorithm>
using namespace std;

//******每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换******//
void HeapAdjust(int *a, int i, int size)  //调整堆 
{
	int lchild = 2 * i;         //i的左孩子节点序号 
	int rchild = 2 * i + 1;     //i的右孩子节点序号 
	int max = i;                //临时变量 
	if (i <= size / 2)          //如果i是叶节点就不用进行调整 
	{
		if (lchild <= size&&a[lchild]>a[max])
		{
			max = lchild;
		}
		if (rchild <= size&&a[rchild]>a[max])
		{
			max = rchild;
		}
		if (max != i)
		{
			swap(a[i], a[max]);
			HeapAdjust(a, max, size);    //避免调整之后以max为父节点的子树不是堆 
		}
	}
}

void BuildHeap(int *a, int size)         //建立堆 
{
	int i;

	//**************建堆的时候:是从底部开始往上层上溯**************//
	for (i = size / 2; i >= 1; i--)      //非叶节点最大序号值为size/2    
	{
		HeapAdjust(a, i, size);
	}
}

void HeapSort(int *a, int size)    //堆排序 
{
	int i;
	BuildHeap(a, size);            //建堆
	for (i = size; i >= 1; i--)
	{
		swap(a[1], a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面 
		//BuildHeap(a,i-1);         //将余下元素重新建立为大顶堆 

		//**************拆堆的时候:是从顶部开始往下层下溯**************//
		HeapAdjust(a, 1, i - 1);    //重新调整堆顶节点成为大顶堆
	}
}

int main(int argc, char *argv[])
{
	//int a[]={0,16,20,3,11,17,8};
	int a[100];
	int size;
	while (scanf("%d", &size) == 1 && size>0)
	{
		int i;
		for (i = 1; i <= size; i++)
			cin >> a[i];
		HeapSort(a, size);
		for (i = 1; i <= size; i++)
			cout << a[i] << " ";
		cout << endl;
	}
	return 0;
}


4、总结:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值