堆排序HeapSort算法学习

本文详细介绍了堆排序算法,包括堆的概念、基本操作、时间复杂度及其应用场景。解释了如何使用最大堆进行排序,并提供了C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在程序设计相关领域,堆(Heap)的概念主要涉及到两个方面:

  • 一种数据结构,逻辑上是一颗完全二叉树,存储上是一个数组对象(二叉堆)。
  • 垃圾收集存储区,是软件系统可以编程的内存区域。

本文所说的堆,指的是前者。

堆排序的时间复杂度是O(nlgN),与快速排序达到相同的时间复杂度。但是在实际应用中,我们往往采用快速排序而不是堆排序。这是因为快速排序的一个好的实现,往往比堆排序具有更好的表现。堆排序的主要用途,是在形成和处理优先级队列方面。另外,如果计算要求是类优先级队列(比如,只要返回最大或者最小元素,只有有限的插入要求等),堆同样是很适合的数据结构。

基础知识

堆一般用数组表示,比如数组A数组的长度Length(A),堆在数组中的元素个数HeapSize(A)。一般说来,HeapSize(A) <= Length(A),因为数组A当中可能有一些元素不在堆中。

假设节点I是数组A中下标为i的节点。

  • Parent(i) : return Floor(i/2); //I的父节点下标,Floor(i)表示比i小的最大整数。
  • Left(i) : return 2*i; //I的左子节点
  • Right(i) : return 2*i+1; //I的右子节点

含有n个元素的堆A的高度是: Floor(lgn)。

堆的基本操作
  • MaxHeapify( A, i ):

    保持堆的性质。假设数组A和下标i,假定以Left(i)和Right(i)为根结点的左右两棵子树都已经是最大堆,节点i的值可能小于其子节点。调整节点i的位置。

  • BuildMaxHeap( A ):

    从一个给定的数组建立最大堆。子数组A[ floor(n/2)+1 .... ... n]中的元素都是树的叶节点(完全二叉树的基本性质)。从索引 ceiling(n/2)开始一直到1,对每一个元素都执行MaxHeapify,最终得到一个最大堆。

  • 堆排序 HeapSort( A ):

    堆排序算法的基本思想是,将数组A创建为一个最大堆,然后交换堆的根(最大元素)和最后一个叶节点x,将x从堆中去掉形成新的堆A1,然后重复以上动作,直到堆中只有一个节点。

  • 优先级队列算法-增加某元素的值(优先级) : HeapIncreaseKey( A, i, key )

    增加某一个元素的优先级后(元素的值),该元素应该向上移动,才能保持堆的性质。

  • 优先级队列算法-插入一个元素: Insert( S, x ) 将x元素插入到优先级队列S中。

    主要思路是,将堆的最后一个叶节点之后,扩展一个为无穷小的新叶节点,然后增大它的值为x的值。

堆排序实现原理

堆排序的C++语言实现
/**
* HeapSort.cpp
* @author arhaiyun
* date: 2013-09-25
**/

#include "stdafx.h"
#include <iostream>

using namespace std;

//[1].数组下表从0开始
void HeapAdjust_0(int *data, int s, int m)
{
	int value = data[s];
	for(int j = 2 * s + 1; j <= m; j = 2 * j + 1)
	{
		if(j < m && data[j] < data[j + 1])
			j++;
		if(value >= data[j])
			break;
		data[s] = data[j];
		s = j;
	}
	data[s] = value;
}

void HeapSort_0(int *data, int length)
{
	if(data == NULL || length <= 0)
		return;
	for(int i = (length / 2 - 1); i >= 0; i--)
	{
		HeapAdjust_0(data, i, length - 1);
	}

	for(int i = length - 1; i > 0; i--)
	{
		int value = data[i];
		data[i] = data[0];
		data[0] = value;

		HeapAdjust_0(data, 0, i - 1);
	}

	for(int i = 0; i < length; i++)
	{
		cout<<data[i]<<" ";
	}
	cout<<endl;
}

//[2].数组下标从1开始的堆排序
void HeapAdjust_1(int *data, int s, int m)
{
	int value = data[s];
	for(int j = 2 * s; j <= m; j *= 2)
	{
		if(j < m && data[j] < data[j + 1])
			j++;
		if(value >= data[j])
			break;
		data[s] = data[j];
		s = j;
	}
	data[s] = value;
}


void HeapSort_1(int *data, int length)
{
	for(int i = length / 2; i > 0; i--)
	{
		HeapAdjust_1(data, i, length);
	}

	for(int i = length; i > 1; i--)
	{
		int value = data[i];
		data[i] = data[1];
		data[1] = value;

		HeapAdjust_1(data, 1, i - 1);
	}

	for(int i = 1; i <= length; i++)
	{
		cout<<data[i]<<"\t";
	}
	cout<<endl;
}

int main(void)
{
	int data[] = {0, 5, 3, 6, 2, 9, 4, 1, 8, 7, 1};
	//HeapSort_1(data, 9);
	HeapSort_0(data, 11);

	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值