`

堆排序算法算法思想和程序

阅读更多
1、 堆排序定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ )

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
【例】关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1)和(2),故它们均是堆,其对应的完全二叉树分别如小根堆示例和大根堆示例所示。
2、大根堆和小根堆
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。
根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。
注意:
①堆中任一子树亦是堆。
②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。
3、堆排序特点
堆排序(HeapSort)是一树形选择排序。
堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。
4、堆排序与直接插入排序的区别
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
5、堆排序
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
/*
堆排序
(1)用大根堆排序的基本思想
① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,
由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
③ 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。
然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,
由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n- 2].keys≤R[n-1..n].keys,
同样要将R[1..n-2]调整为堆。
……
直到无序区只有一个元素为止。
(2)大根堆排序算法的基本操作:
① 初始化操作:将R[1..n]构造为初始堆;
② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
注意:
①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。
堆排序和直接选择排序相反:在任何时刻,堆排序中无序区总是在有序区之前,
且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。 
*/

#include <iostream>
//生成大根堆
void HeapAdjust(int SortData[],int StartIndex, int Length)
{
	while(2*StartIndex+1 < Length)
	{
		int MinChildrenIndex = 2*StartIndex+1 ;
		if(2*StartIndex+2 < Length )
		{
			//比较左子树和右子树,记录最大值的Index
			if(SortData[2*StartIndex+1]<SortData[2*StartIndex+2])
			{
				MinChildrenIndex = 2*StartIndex+2;
			}
		}
		if(SortData[StartIndex] < SortData[MinChildrenIndex])
		{
			//交换i与MinChildrenIndex的数据
			int tmpData =SortData[StartIndex];
			SortData[StartIndex] =SortData[MinChildrenIndex];
			SortData[MinChildrenIndex] =tmpData;
			//堆被破坏,需要重新调整
			StartIndex = MinChildrenIndex ;
		}
		else
		{
			//比较左右孩子均大则堆未破坏,不再需要调整
			break;
		}
	}

	return;
}

//堆排序
void HeapSortData(int SortData[], int Length)
{
	int i=0;

	//将Hr[0,Lenght-1]建成大根堆
	for (i=Length/2-1; i>=0; i--)
	{
		HeapAdjust(SortData, i, Length);
	}

	for (i=Length-1; i>0; i--)
	{
		//与最后一个记录交换
		int tmpData =SortData[0];
		SortData[0] =SortData[i];
		SortData[i] =tmpData;
		//将H.r[0..i]重新调整为大根堆
		HeapAdjust(SortData, 0, i);
	}

	return;
}

//TestCase
int main()
{
	int SortData[] ={12,36,24,85,47,30,53,91};

	HeapSortData(SortData, 8);

	for (int i=0; i<8; i++)
	{
		std::cout<<SortData[i]<<" ";
	}
	std::cout<<std::endl;

	return 0;
}


原文网址:http://www.maycode.com/index.php/hotspot/27-clanguage/1123-cpp.html
分享到:
评论

相关推荐

    7大排序算法实现程序(快速排序,冒泡排序,选择排序,归并排序,插入排序,希尔排序,堆排序)

    本资源提供了七大经典排序算法的实现程序,包括快速排序、冒泡排序、选择排序、归并排序、插入排序、希尔排序和堆排序。下面将逐一详细介绍这些排序算法及其原理。 1. 快速排序:由C.A.R. Hoare提出,是一种采用...

    堆排序算法源代码

    在这个名为"sort"的压缩包中,很可能包含了实现堆排序算法的C/C++源文件。 堆排序的核心思想是利用树形数据结构——堆(Heap)来完成排序。堆是一个近似完全二叉树的结构,同时满足大顶堆(父节点的值大于或等于其...

    算法设计实验报告堆排序代码

    【堆排序算法详解】 堆排序是一种高效的比较排序算法,其主要思想是利用堆这种数据结构进行数据的排序。堆是一个近似完全二叉树的结构,同时满足堆的性质:即父节点的键值总是大于或等于(在最大堆中)或小于或等于...

    排序算法编程 堆排序 快速排序

    在实际应用中,选择合适的排序算法能够极大地提高程序的效率和性能。 总结一下,这四种排序算法各有特色,适用场景不同。堆排序和快速排序是基于比较的排序,而基数排序和计数排序是非比较型的。理解并能熟练运用...

    C++语言的算法实现包括插入排序冒泡排序堆排序快速排序

    本文将深入探讨四种在C++中实现的常见排序算法:插入排序、冒泡排序、堆排序和快速排序。这些算法各有特点,适用于不同的场景,理解并掌握它们对于提升编程能力至关重要。 1. **插入排序**: 插入排序是一种简单的...

    堆排序算法C语言程序.zip

    在本文中,我们将深入探讨堆排序算法的原理、C语言实现以及其在实际应用中的优势。 堆排序算法的核心在于“堆”这一数据结构。堆是一个近似完全二叉树的结构,同时满足堆属性:对于任意非叶子节点i,其子节点的键值...

    C++实现常用排序算法(快速,归并,选择,谢尔,堆排序)

    本文将深入探讨五种常用的排序算法:快速排序、归并排序、选择排序、谢尔排序和堆排序。 **快速排序** 是由C.A.R. Hoare在1960年提出的,是一种效率较高的分治策略。其基本思想是通过一趟排序将待排序的数据分割成...

    实验(五)快速排序算法和堆排序算法的设计.doc

    通过这种方式,用户可以选择快速排序或堆排序算法,实现对学生考试成绩的高效排序。 总结: 本实验旨在让学生掌握两种经典的排序算法——快速排序和堆排序。快速排序以其平均时间复杂度为O(n log n)而著称,而堆...

    常用排序算法源程序

    学习和理解这些源代码,可以帮助开发者深入理解排序算法的原理,并能在实际项目中灵活运用,提升程序的效率。同时,通过阅读和分析这些代码,还能锻炼分析问题和解决问题的能力,对提升编程技能大有裨益。

    Java排序算法练习:1.快速排序 2.归并排序 3.插入排序 4.冒泡排序 5.选择排序 6.堆排序

    这里我们将深入探讨标题和描述中提到的六种排序算法:快速排序、归并排序、插入排序、冒泡排序、选择排序以及堆排序。 1. **快速排序**:由C.A.R. Hoare在1960年提出,是一种高效的分治算法。快速排序的基本思想是...

    排序技术,整合各种排序算法思想

    总之,了解和掌握这些排序算法有助于我们根据具体需求选择合适的排序方式,优化程序性能,提高数据处理的效率。在实际编程中,还可以结合各种算法的优缺点,设计出更加高效的混合排序策略,以应对复杂多变的排序问题...

    堆排序算法--源程序

    堆排序的源程序--编译、运行成功的。 其基本算法思想参照《算法导论》。 有点编译器需去掉-system("pause");

    堆排序算法

    在Linux环境下,我们可以利用C、C++等编程语言来实现堆排序算法,并在Ubuntu 13.04这样的操作系统上运行。下面,我们将详细讨论堆排序的基本原理、实现步骤以及如何在Ubuntu上编译和运行相关程序。 ### 堆排序的...

    排序算法的实现

    在编程领域,排序算法是计算机科学中的核心概念,特别是在数据处理和数据分析方面。本文将详细介绍在C语言中实现的八种排序算法,并探讨每种算法的工作原理、性能特点以及适用场景。 1. 冒泡排序(Bubble Sort): ...

    数据结构课程设计(C++代码+报告)--各种排序算法时间性能的比较

    在这个项目中,我们研究了六种不同的排序算法:快速排序、冒泡排序和堆排序,以及其他三种未明确提及的排序算法。接下来,我们将逐一探讨这些算法的原理和时间性能。 1. **快速排序**:由C.A.R. Hoare提出的快速...

    基本的排序算法(堆排序,插入排序,折半插入,归并,基数,希尔排序等)

    在计算机科学领域,排序...了解和掌握这些排序算法对于任何IT专业人员来说都是非常重要的,因为它们不仅帮助我们理解算法设计的基本思想,而且在实际编程中,根据具体需求选择合适的排序算法能够显著提升程序的效率。

    八种排序算法程序(算法与设计,数据结构)

    7. **2路归并排序**:归并排序是一种稳定的排序算法,采用分治思想。它将序列分为两半,分别进行排序,然后将两个有序子序列合并成一个有序序列。2路归并排序在合并过程中通常使用两个辅助数组。 8. **折半插入排序...

    用C语言实现常用排序算法

    本项目旨在实现并比较六种经典的排序算法——直接插入排序、折半插入排序、起泡排序、简单选择排序、堆排序以及2-路归并排序,使用C语言编程。为了全面评估这些算法,我们将在一组随机生成的30000个整数上运行它们,...

    常用排序算法介绍_示例程序|排序算法_程序.rar

    首先,让我们逐一探讨这些排序算法的核心思想: 1. **冒泡排序**:通过不断交换相邻的逆序元素,使得较大的元素逐渐“浮”到序列末尾,直至整个序列有序。 2. **选择排序**:每次从未排序的部分中找到最小(或最大...

Global site tag (gtag.js) - Google Analytics