二叉堆和堆排序
来源:互联网 发布:unity3d c 工具类脚本 编辑:程序博客网 时间:2024/05/14 16:31
(二叉)堆是一个数组,它可以近似看作完全二叉树。树上的每一个节点对应数组中的一个元素。除了最底层,该树是完全充满的,而且是从左向右填充。
根据节点下标可以求出对应的子树和双亲
PARENT(i) return [i/2] //i表示数组中的第几个元素,[i/2]表示取整数 LEFT(i) return 2*i RIGHT(i) return 2*i+1
二叉堆可分为最大堆和最小堆。堆顶元素(根节点元素)比其它节点元素都大的堆并且任何双亲节点都不小于子节点是最大堆,反之堆顶元素比其它节点元素都小,并且任何双亲节点都不大于子节点的堆是最小堆。
A是数组
最大堆 A[PARENT(i)]>=A[i] (常用用于堆排序)
最小堆A[PARENT(i)]<=A[i] (常用于优先队列)
堆的一些基本操作,比如建堆,调整堆,堆排序的时间复杂度是O(lg n)。堆的高度是lgn。
下面给出维护堆的伪代码
MAX-HEAPIFY(A, i)1 l=LEFT(i) //获取左子树位置2 r=RIGHT(i) //获取右子树位置3 if l<=A.heap-size and A[l]>A[i]4 largest=l;5 else largest=I6 if r<=A.heap-size and A[r]>A[i]7 largest=r8 if largest 不等于 i9 exchange A[I] with A[largest] MAX-HEAPIFY(A, largest) //递归调用,因为交换可能会破坏堆性质
我们从完全二叉树的性质上来分析,字数组A(|n/2|+1…n)中的元素都是树的叶节点,豆哥叶节点都可以看成只包含一个元素的堆。那么建堆我们只需要从非A(|n/2|+1…n)的数组元素开始调用建堆过程就可以了。下面给出伪代码
BUILD-MAX-HEAP(A)1 A.heap-size=A.length2 for I=A[A.length/2] down to 13 MAX-HEAPIFY(A,i)
堆的用途之一是用于排序的堆排序。在建立完成最大堆(按升序排序数组,最小堆就是按降序排序数组)之后,注意到整个数组的 最大元素 总是在最大堆的第一个,即a[0]。这时,如果我们拿走第一个元素,放到数组的最后一个位置,然后对第一个元素进行维护最大堆maxHeapify,如此循环进行,便可完成整个数组的排序。下面给出伪代码
HEAPSORT(A)1 BUILD-MAX-HEAP(A)2 for i=A.length down to 23 exchange A[1] with A[i]4 A.heap-size--5 MAX-HEAPIFY(A,1)
完整示例代码
import org.junit.Test;/** * Created by WuNanliang on 2017/5/3. * 堆数据结构 */public class HeapDemo { @Test public void testDemo() { int[] arr = {10, 8, 11, 8, 14, 9, 4, 1, 17}; heapSort(arr); for (int num : arr) System.out.print(num + " "); } /** * 左子树的位置 * * @param parentIndex 双亲节点位置 * @return */ private int leftChildIndex(int parentIndex) { return 2 * parentIndex + 1;//因为根节点index=0 } /** * 右子树的位置 * * @param parentIndex 双亲节点位置 * @return */ private int rightChildIndex(int parentIndex) { return 2 * parentIndex + 2;//因为根节点index=0 } private void swap(int[] arr, int i, int j) { arr[j] = arr[i] + arr[j]; arr[i] = arr[j] - arr[i]; arr[j] = arr[j] - arr[i]; } /** * 维护最大堆 * * @param arr 数组 * @param currentIndex 当前位置 * @param length 数组的长度 */ private void maxHeapify(int[] arr, int currentIndex, int length) { int leftIndex = leftChildIndex(currentIndex); int rightIndex = rightChildIndex(currentIndex); //largestIndex 记录leftIndex/rightIndex/currentIndex最大值 int largestIndex; if (leftIndex < length && arr[leftIndex] > arr[currentIndex]) largestIndex = leftIndex; else largestIndex = currentIndex; if (rightIndex < length && arr[rightIndex] > arr[largestIndex]) largestIndex = rightIndex; if (largestIndex != currentIndex) { swap(arr, currentIndex, largestIndex); //递归维护堆性质 maxHeapify(arr, largestIndex, length); } System.out.println("index:" + currentIndex + "->" + arr[currentIndex]); } /** * 建立最大堆 * * @param arr */ private void buildMaxHeap(int[] arr) { int len = arr.length; int middleIndex = len / 2; for (int i = middleIndex + 1; i >= 0; i--) maxHeapify(arr, i, len); } private void heapSort(int[] arr) { buildMaxHeap(arr); int len = arr.length; for (int i = len - 1; i >= 1; i--) { swap(arr, i, 0); len--; maxHeapify(arr, 0, len); } }}
参考资料
1《算法导论 原书第3版》
2 堆排序以及最大优先队列
0 0
- 二叉堆和堆排序
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- heapSort - 堆排序 / 二叉堆
- heapSort - 堆排序 / 二叉堆
- 二叉堆(堆排序)
- 二叉堆与堆排序
- (二叉堆,堆排序)
- 数据结构 二叉堆 & 堆排序
- 二叉堆与堆排序
- 新手讲排序:堆排序 和 认识二叉堆
- 堆和堆排序
- 堆和堆排序
- 堆和堆排序
- 堆和堆排序
- 堆和堆排序
- 2440超详细uboot移植笔记(十一)------支持NAND FLASH
- JQuery zClip插件实现复制到剪贴板功能
- 数轴上覆盖最多点的数目
- spring注解@service("service")括号中的service有什么用
- Java中的注解是如何工作的?
- 二叉堆和堆排序
- Spring框架入门
- 在两台虚拟机之间实现SSH免密码登录
- 给Android程序员的一些建议
- linux设备上的Onvif 实现1:onvif规范 中文介绍
- openlayers2 开发如何判断一个marker所在的点是否在一个多边形内部
- 微信小程序之点击列表的item带参数跳转界面
- python数据分析---Pandas
- VGG-大规模图像识别的深度卷积网络 Very Deep Convolutional Networks for Large-Scale Image Recognition