算法学习之堆排序算法

堆排序算法:

1、像合并排序算法一样,运行时间都为O(nlgn);

2、像插入排序算法一样, 都是原地排序算法,不需要开销多余的内存空间;


一、堆的介绍

首先,将我们需要排序的数列转化为一颗完全二叉树。树中的每一个节点与数组中的存放该节点值的那个元素对应。

假设:我们需要排序:int arr[] = {3, 2, 1, 9, 11, 4, 5}这个数列,则将它转化为二叉树,如图所示:



二叉树的类型有两种:

1、最大堆:除了树根以外的每个节点i,都有A[PARENT(i)] >= A[i],即某个节点的值至多和父类节点的值一样大;

2、最小堆:除了树根以外的每个节点i,都有A[PARENT(i)] <= A[i],即某个节点的值至少和父类节点的值一样小;

 注:一般都用最大堆,也可以用最小堆, 这里后面的代码用的是最大堆的。


二、堆的排序

所谓堆的排序,就是将某一节点与它的子节点(左、右(如果有的话))按照最大堆的特点进行排序和替换。这里有一个很重要的前提条件:假设该节点的子节点(左、右)为根的两颗二叉树都是最大堆。

承接上面例子:

对index = 3, Value = 1的节点来说,进行排序, 该节点比它的左子节点和有右子节点都要小,则在三个节点中找到一个最大的节点替换index = 3, Value = 1的节点。


转换成:


三、创建最大堆

创建最大堆:将所有有子节点的节点进行堆的排序,从最大索引节点开始,到最小索引节点结束。 即从3开始, 到1结束。 这样就符合了堆排序的重要前提条件。

将上述数列进行创建最大堆后,如图所示:


四、堆排序算法

根据步骤三,创建了当前的最大的堆排序,其中arr[1]为该数列的最大数值。

然后将arr[1]与arr[length(arr)]替换。

再次对剩余的数值进行创建最大堆, index 从1 到 length(arr - 1),因为length(arr)已经最最大值了,没有必要将它加入进行排序了。

获取后的arr[1]为剩余数列的最大数值。 然后将arr[1]与arr[length(arr) - 1 ]进行替换。

这样以此类推,只到剩余最后一个数值, 在该数值为最小。


代码如下:

/*
* filename : heapsort.cpp
* author : Becky
* date : 2015 - 02 - 11
*/

/*include*/
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*define*/

void Exchage2Value(int *_leftValue, int *_rightValue)
{
	int temp = *_leftValue;
	*_leftValue = *_rightValue;
	*_rightValue = temp;
}

int GetParentIndex(int _index)
{
	return _index / 2;
}

int GetLeftIndex(int _index)
{
	return _index * 2;
}

int GetRightIndex(int _index)
{
	return _index * 2 + 1;
}

void Max_Heap(int *_pArr, int _index, int _heaplength)
{
	int index = _index - 1;
	int leftIndex = GetLeftIndex(_index) - 1;
	int rightIndex = GetRightIndex(_index) - 1;
	int maxIndex = 0;
	int heaplength = _heaplength - 1;

	if (leftIndex <= heaplength && rightIndex <= heaplength)
	{
		if (_pArr[index] >= _pArr[leftIndex] && _pArr[index] >= _pArr[rightIndex])
			return;

		if (_pArr[index] < _pArr[leftIndex] && _pArr[index]  >= _pArr[rightIndex])
		{
			maxIndex = leftIndex;
			Exchage2Value(_pArr + index, _pArr + leftIndex);
		}	

		if (_pArr[index] < _pArr[rightIndex] && _pArr[index] >= _pArr[leftIndex])
		{
			maxIndex = rightIndex;
			Exchage2Value(_pArr + index, _pArr + rightIndex);
		}

		if (_pArr[index]  < _pArr[leftIndex] && _pArr[index] < _pArr[rightIndex])
		{
			maxIndex = _pArr[leftIndex] >= _pArr[rightIndex] ? leftIndex: rightIndex;

			Exchage2Value(_pArr + index, _pArr + maxIndex);
		}
		
	}
	else if (leftIndex <= heaplength)
	{
		if ( _pArr[index] >= _pArr[leftIndex] )
			return;

		if (_pArr[index] < _pArr[leftIndex])
		{
			maxIndex = leftIndex;
			Exchage2Value(_pArr + index, _pArr + leftIndex);
		}
	}
	else 
		return;

	Max_Heap(_pArr, maxIndex + 1, _heaplength);
	return ;
}

void Build_Max_Heap(int *_pArr, int _heaplength)
{
	for (int i = _heaplength / 2 ; i != 0; i--)
	{
		Max_Heap(_pArr, i,  _heaplength);
	}
	return;
}

void Heap_sort(int *_pArr, int _arrLength)
{
	int arrLength = _arrLength;
	
	int heapLength = _arrLength;
	Build_Max_Heap(_pArr, heapLength);

	for (int i = arrLength - 1; i != 0; i--)
	{
		Exchage2Value(_pArr + i, _pArr);
		Build_Max_Heap(_pArr, --heapLength);
	} 
	
	return;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int arr[] = {3, 2, 1, 9, 11, 4, 5, 3, 7, 8, 6, 10};
	Heap_sort(arr, sizeof(arr) / 4);

	for (int i = 0; i != sizeof(arr) / 4; i++)
	{
		printf("%d\t", arr[i]);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值