【算法】堆排序

堆排序

上一篇博客讲了堆这种数据结构,它提供了一种接口getMax接口,好消息是获得最大值的时间复杂度仅仅为O(lgn),因此联想到之前的选择排序算法,

每次从剩下的未排序元素中找到极值元素,将其放入对应的位置。

由于一般的选择排序在寻找最大值时需要遍历数组,遍历数组的复杂度为O(n),因此造成了时间的浪费,如若将待排序的数组进行一系列整理,例如将其整理成有特点的堆这种数据结构。那么我们有理由相信,能将选择排序的时间复杂度降低到O(nlgn)

堆排序算法

具体的堆排序算法如下,很容易理解

HEAP-SORT(A)
	// 利用数组A建最大堆
	CREATE-HEAP(A)
	for i= n-1 to 1
		exchange A[0] A[i]
		heap.size=heap.size-1;
		// 由于交换可能会导致不满足堆的有序性,需要调整:下滤
		Adjust(A,0)

于是在Heap类中添加一个排序的方法

public void heapSort(int[] heapArr) {
		createHeapFloyd(heapArr);// 下标为0----n-1中保存着一个最大堆
		for (int i = n - 1; i >= 1; i--) {
			swap(heapArray, 0, i);
			n--;
			// 调整新的堆的顺序性
			percolateDown(0);
		}
	}

当调用heapSort后里面的堆已经被排好序了。然而这样还不够直接,如果将建堆时的操作改成

public void createHeapFloyd(int[] heapArr) {
//		System.arraycopy(heapArr, 0, heapArray, 0, heapArr.length);
		heapArray = heapArr;
		n = heapArr.length;
		for (int i = (n - 1) >> 1; i >= 0; i--) {
			percolateDown(i);
		}
	}

即直接将待排序的数组赋给堆中维护的数组,性能更好。

堆排序的性能

这样调用堆排序后,数组已经有序,并且还不需要额外的内存空间,除了交换产生固定的空间消耗以外。即空间复杂度为O(1)

堆排序是一种不稳定的排序算法,这是显然的,因为如果找到未排序部分的元素会和后面的交换,已排序部分的指针前移,再次有一个相同元素会放在前面,故而和原始顺序相反。

测试

public static void main(String[] args) {
		Heap heap = new Heap(100);
		int arr[] = new int[]{10,5,13,8,6,78,4,6};
		heap.heapSort(arr);
		for (int i : arr) {
			System.out.print(i + "  ");
		}
	}

输出序列为

4  5  6  6  8  10  13  78

时间: 2024-09-28 12:02:20

【算法】堆排序的相关文章

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

算法—堆排序

我们可以把任意优先队列变成一种排序方法.将所有元素插入一个查找最小元素的优先队列,然后再重复调用删除最小元素的操作来将它们按顺序删去.用无序数组实现的优先队列这么做相当于进行一次插入排序.用基于堆的优先队列这样做等同于哪种排序?一种全新的排序方法!下面我们就用堆来实现一种经典而优雅的排序算法——堆排序. 堆排序可以分为两个阶段.在堆的构造阶段中,我们将原始数组重新组织安排进一个堆中:然后在下沉排序阶段,我们从堆中按递减顺序取出所有元素并得到排序结果.为了排序的需要,我们不再将优先队列的具体表示隐

经典排序算法 - 堆排序Heap sort

经典排序算法 - 堆排序Heap sort 堆排序有点小复杂,分成三块 第一块,什么是堆,什么是最大堆 第二块,怎么将堆调整为最大堆,这部分是重点 第三块,堆排序介绍 第一块,什么是堆,什么是最大堆 什么是堆 这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构. 堆可以视为一棵完全的二叉树,完全二叉树的一个"优秀"的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素. 数组与堆之间的关系 二叉堆一般分为两种:最大堆和最小堆. 什么

Java排序算法 - 堆排序的代码

把内容过程中比较重要的一些内容片段做个备份,如下的资料是关于Java排序算法 - 堆排序的内容. import java.util.Arrays; public class HeapSort { int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51}; public HeapSort(){ heapSort(a); } public void heapSort(int[

算法----堆排序(heap sort)

堆排序是利用堆进行排序的高效算法,其能实现O(NlogN)的排序时间复杂度,具体算法分析可以点击堆排序算法时间复杂度分析. 算法实现: 调整堆: void sort::sink(int* a, const int root, const int end) { int i=root; while(2*i +1 <= end) { int k = 2*i+1; if(k+1<=end && a[k]<a[k+1]) k++; if(a[k] < a[i]) break;

经典排序算法——堆排序

对于一个int数组,请编写一个堆排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] class HeapSort { public: int* heapSort(int* A, int n) { BuildMaxHeap(A, n);//首先将数组A构建成大顶堆 for (int i = n - 1; i >= 1; i--) { swap(A[0],A[i]);//将堆顶最大值与未排序的最

排序算法-堆排序

堆排序算法是建立在堆这种数据结构的基础上,其实堆听着很高端,其实很简单,就是一个二叉树,但是又特殊条件,就是其父节点比孩子节点都大(或都小)的堆称为最大堆(最小堆),瞬间感觉很简单了,最简单的保存方法就是直接用数组来保存. 给出一组数,我们要使用堆排序,首先需要建堆,但是这一组数首先肯定是不满足上面堆的性质的,所以我们需要调整,让他满足堆得性质,变成一个堆,怎么调整呢?拿最大堆来说,就是对于一个节点,我们判断其孩子是否有比父亲节点大的,有的话,交换这两个值,这样父亲就比孩子都大了,当然交换完了之

算法 - 堆排序

堆排序 Heap Sort 堆排序是一种选择排序,其时间复杂度为O(nlogn). 堆的定义 n个元素的序列{k1,k2,-,kn}当且仅当满足下列关系之一时,称之为堆. 情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小顶堆) 情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大顶堆) 其中i=1,2,-,n/2向下取整; 若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点

排序算法——堆排序

堆排序 ①了解二叉堆的定义 ②一般用数组表示堆 注意逻辑存储结构和实际存储结构 ③i节点的 父节点(i-1)/2 子节点 左2*i+1 右2*i+2 ④注意每种操作的思想 ⑤一般数组要堆化操作后再进行堆排序 代码实现 /*本栗子是最小堆*//*从第i个节开始调整*/ void MinHeapDown(int a[],int i,int n) { int j=0,temp=0; temp = a[i]; j=2*i+1;/*i节点的左孩子*/ while(j < n) { if(j+1<n &a

数据结构与算法——堆排序

代码: void HeapSort(int a[], int n){    int Tmp;    for (int i = n / 2; i >= 0; i--)        PercDown(a, i, n);    /*build a heap; we should know that intinially we put all of the  elements randomly, then    we begin to percolate down the heap from the