【算法导论】堆排序

简介:         堆排序像合并排序一样,时间复杂度为O(nlogn);像插入排序一样,是一种原地排序(在任何时候只有常数个元素存储在数组外)。         二叉堆的概念:是一种数组对象,可以被视为一棵完全二叉树,树的每一层都是填满的,最后一层可能除外。

        堆排序像合并排序一样,时间复杂度为O(nlogn);像插入排序一样,是一种原地排序(在任何时候只有常数个元素存储在数组外)。

        二叉堆的概念:是一种数组对象,可以被视为一棵完全二叉树,树的每一层都是填满的,最后一层可能除外。

        二叉树有两种:最大堆和最小堆。最大堆:父节点不小于子节点。最小堆:父节点不大于子节点。在堆排序中我们使用最大堆;最小堆通常在构造优先队列时使用。

        进行堆排序分为三个模块:1.保持最大堆性质;2.建堆;3:进行排序。

        1.保持最大堆性质即使以i为根的子树成为最大堆

            可以由下图为例:

         

   具体程序如下

/*****************************************\
 输入:原始数组arrayA 父节点的下标i             
 功能:使以i为根的子树成为最大堆
 时间复杂度:lgn即树的层数
\*****************************************/

void MaxHeapify(int* arrayA,int n,int i)//i为父节点的在数组的下标
{
	
	int Length=n;
	
	int l=2*i;//l为左子节点的在数组的下标
	int r=l+1;//r为右子节点的在数组的下标
	int largest=0;
	int temp=0;

	if((l<Length)&&(arrayA[l]>arrayA[i]))
       largest=l;
	else
		largest=i;
	if((r<Length)&&(arrayA[r]>arrayA[largest]))
	    largest=r;
	if(largest!=i)
	{
		temp=arrayA[i];
		arrayA[i]=arrayA[largest];
		arrayA[largest]=temp;
		MaxHeapify(arrayA,n,largest);
	}
}

    2.建堆:使数组arrayA中的元素成为最大堆

     


具体程序如下

/*****************************************\
 输入:原始数组arrayA              
 功能:使数组arrayA中的元素成为最大堆
 时间复杂度:nlgn
\*****************************************/
void BuildMaxHeap(int* arrayA,int n)
{
	for(int i=n/2;i>0;i--)
		MaxHeapify(arrayA,n,i);
}

3.堆排序

   主要思想是将每次的堆的顶节点与最末的叶节点进行交换,然后重新根据最大堆性质使得顶节点(根)成为最大值,如此循环。

   

具体程序如下:

/*****************************************\
 输入:原始数组arrayA              
 功能:进行从小到大的排序
 时间复杂度:nlgn
\*****************************************/
void HeapSort(int* arrayA,int n)
{
	int temp=0;
	int Length=n;
	for(int i=Length-1;i>=2;i--)
	{
		temp=arrayA[1];
		arrayA[1]=arrayA[i];
		arrayA[i]=temp;
		n--;
		MaxHeapify(arrayA,n,1);
	   
	}
}

下面将三个步骤综合起来,总的排序算法程序如下

#include<iostream>
#include<ctime> 
using namespace std;

void MaxHeapify(int* arrayA,int n,int i);//保持最大堆的性质
void BuildMaxHeap(int* arrayA,int n);//构造堆
void HeapSort(int* arrayA,int n);//进行堆排序

void main()
{

	int arrayA[11]={0,4,1,3,2,16,9,10,14,8,7};//第一个空间不用,是为了方便下标计算

	int Length=sizeof(arrayA)/sizeof(int);//数组的长度

	BuildMaxHeap(arrayA,Length);//利用数组arrayA建立最大堆

	cout<<"原序列为:";
    for(int i=0;i<Length;i++)
		cout<<arrayA[i]<<" ";
	cout<<endl;

	HeapSort(arrayA,Length);

	cout<<"排序好的序列为:";
	for(int i=0;i<Length;i++)
		cout<<arrayA[i]<<" ";
	cout<<endl;



}

/*****************************************\
 输入:原始数组arrayA 父节点的下标i             
 功能:使以i为根的子树成为最大堆
 时间复杂度:lgn即树的层数
\*****************************************/

void MaxHeapify(int* arrayA,int n,int i)//i为父节点的在数组的下标
{
	
	int Length=n;
	
	int l=2*i;//l为左子节点的在数组的下标
	int r=l+1;//r为右子节点的在数组的下标
	int largest=0;
	int temp=0;

	if((l<Length)&&(arrayA[l]>arrayA[i]))
       largest=l;
	else
		largest=i;
	if((r<Length)&&(arrayA[r]>arrayA[largest]))
	    largest=r;
	if(largest!=i)
	{
		temp=arrayA[i];
		arrayA[i]=arrayA[largest];
		arrayA[largest]=temp;
		MaxHeapify(arrayA,n,largest);
	}
}


/*****************************************\
 输入:原始数组arrayA              
 功能:使数组arrayA中的元素成为最大堆
 时间复杂度:nlgn
\*****************************************/
void BuildMaxHeap(int* arrayA,int n)
{
	for(int i=n/2;i>0;i--)
		MaxHeapify(arrayA,n,i);
}


/*****************************************\
 输入:原始数组arrayA              
 功能:进行从小到大的排序
 时间复杂度:nlgn
\*****************************************/
void HeapSort(int* arrayA,int n)
{
	int temp=0;
	int Length=n;
	for(int i=Length-1;i>=2;i--)
	{
		temp=arrayA[1];
		arrayA[1]=arrayA[i];
		arrayA[i]=temp;
		n--;
		MaxHeapify(arrayA,n,1);
	   
	}
}

注意:我是在vs2008上运行的,与vc 6.0有点区别,主要是循环体中的循环变量的作用域,出错体现在循环变量的重复定义上。例如:在vs2008或vs2010上,程序为:

#include<stdio.h>
void main()
{
int i=0;
for(int i=0;i<5;i++)
printf("%d ",i);
}

则在VC 6.0上需改为:

#include<stdio.h>
void main()
{
int i=0;
for(i=0;i<5;i++)
printf("%d ",i);
} 



原文:http://blog.csdn.net/tengweitw/article/details/9152899

作者:nineheadedbird


目录
相关文章
|
1月前
|
算法 Python
数据结构算法--4堆排序
堆排序过程概述:建立大根堆,将堆顶最大元素移出并替换为末尾元素,调整保持堆性质,重复此过程直至堆为空,实现排序。时间复杂度为O(nlogn)。Python中可用heapq模块进行堆操作。
|
2月前
|
机器学习/深度学习 人工智能 算法
数据结构与算法:堆排序和TOP-K问题
朋友们大家好,本节内容来到堆的应用:堆排序和topk问题
数据结构与算法:堆排序和TOP-K问题
|
2月前
|
存储 人工智能 算法
深入浅出堆排序: 高效算法背后的原理与性能
深入浅出堆排序: 高效算法背后的原理与性能
65 1
|
2月前
|
移动开发 算法 前端开发
前端算法之堆排序
前端算法之堆排序
26 1
|
1月前
|
搜索推荐 算法 Java
Java中的快速排序、归并排序和堆排序是常见的排序算法。
【6月更文挑战第21天】Java中的快速排序、归并排序和堆排序是常见的排序算法。快速排序采用分治,以基准元素划分数组并递归排序;归并排序同样分治,先分割再合并有序子数组;堆排序通过构建堆来排序,保持堆性质并交换堆顶元素。每种算法各有优劣:快排平均高效,最坏O(n²);归并稳定O(n log n)但需额外空间;堆排序O(n log n)且原地排序,但不稳定。
23 3
|
1月前
|
搜索推荐 算法
【C/排序算法】:堆排序和选择排序
【C/排序算法】:堆排序和选择排序
14 0
|
1月前
|
存储 算法 C语言
数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)
数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)
22 0
|
2月前
|
人工智能 搜索推荐 算法
sort-04-heap sort 堆排序算法详解
这是一个关于排序算法的系列文章摘要,包括了10篇关于不同排序算法的链接,如冒泡排序、快速排序、选择排序、堆排序等。堆排序是一种基于比较的排序算法,利用了近似完全二叉树的结构并满足最大堆或最小堆的性质。最大堆中,每个节点的值都大于或等于其子节点。文章详细解释了最大堆的概念、节点访问方式以及堆的操作,包括堆调整和堆排序的过程,并通过图解展示了堆排序的具体步骤。此外,还提供了一个Java实现的堆排序代码示例。整个排序系列来源于一个开源项目,读者可以通过链接查看完整内容。
sort-04-heap sort 堆排序算法详解
|
2月前
|
算法 搜索推荐
数据结构与算法⑫(第四章_中_续一)堆排序(详解)
数据结构与算法⑫(第四章_中_续一)堆排序(详解)
30 0
|
2月前
|
人工智能 算法 搜索推荐
直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”
直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”

热门文章

最新文章