堆 heap
来源:互联网 发布:手机淘宝怎么实名 编辑:程序博客网 时间:2024/06/05 04:31
堆(英语:Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。
逻辑定义
n个元素序列{k1,k2…ki…kn},当且仅当满足下列关系时称之为堆:
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2)
堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。
任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
二叉堆
二叉堆故名思议是一种特殊的堆,二叉堆具有堆的性质(父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值),二叉堆又具有二叉树的性质(二叉堆是完全二叉树或者是近似完全二叉树)。当父节点的键值大于或等于(小于或等于)它的每一个子节点的键值时我们称它为最大堆(最小堆)。
完全二叉树是增加了限定条件的二叉树。假设一个二叉树的深度为n。为了满足完全二叉树的要求,该二叉树的前n-1层必须填满,第n层也必须按照从左到右的顺序被填满。
插入
新插入的节点new放在完全二叉树最后的位置,再和父节点比较。如果new节点比父节点小,那么交换两者。交换之后,继续和新的父节点比较…… 直到new节点不比父节点小,或者new节点成为根节点。
删除
让最后一个节点last成为新的节点,从而构成一个新的二叉树。再将last节点不断的和子节点比较。如果last节点比两个子节点中小的那一个大,则和该子节点交换。直到last节点不大于任一子节点都小,或者last节点成为叶节点。
以下C代码可以直接运行,有不妥当的地方望指正~
/*堆使用数组arr实现堆,arr[0]来存储堆的大小,从arr[1]开始存储元素构建的是小顶堆*/#include <stdio.h>void buildHeap(int *arr,int n);void insert(int *arr,int target);void bottom_up(int *arr);void top_down(int *arr);int delete_root(int *arr);void heapSort(int *arr);/*arr:堆数组n: 要建的堆的长度*/void buildHeap(int *arr,int n){ int i=1; for(;i<=n;i++) insert(arr,arr[i]);}/*插入操作,把新插入的节点放在完全二叉树最后面的位置,然后开始自下而上的比较,如果新节点比其父节点小(小顶堆),那就进行交换;新的父节点在与其父节点进行比较...直到儿子节点大于父节点或者到达顶节点结束*//*arr: 堆数组target:要插入的元素*/void insert(int *arr,int target){ arr[0]++; arr[arr[0]]=target; bottom_up(arr);}void bottom_up(int *arr)//自下而上处理 从最后一个元素往上处理{ int nChild=arr[0]; int parent=nChild/2; while(parent>0 && arr[nChild]<arr[parent]) { arr[nChild]=arr[nChild]^arr[parent]; arr[parent]=arr[nChild]^arr[parent]; arr[nChild]=arr[nChild]^arr[parent]; nChild=parent; parent=nChild/2; }}/*删除操作:只能删除根节点,根节点删除后,会得到两个子树,需要进行重构堆,进行的操作为,让最后一个节点last成为根节点,然后进行向下比较,如果根节点大于其中一个儿子节点,则交换位置,直到父节点不大于儿子节点或到叶子为止。*/int delete_root(int *arr){ if(arr[0]<1) return -1; int res=arr[1]; int nChild=arr[0]; arr[0]--; arr[nChild]=arr[nChild]^arr[1]; arr[1]=arr[nChild]^arr[1]; arr[nChild]=arr[nChild]^arr[1]; top_down(arr); return res;}void top_down(int *arr)//从第一个元素往下处理{ int nChild; int parent=1; nChild=parent<<1; while(nChild<=arr[0]) { if(nChild+1<=arr[0] && arr[nChild]>arr[nChild+1]) nChild++; if(arr[parent]<=arr[nChild]) break; arr[nChild]=arr[nChild]^arr[parent]; arr[parent]=arr[nChild]^arr[parent]; arr[nChild]=arr[nChild]^arr[parent]; parent=nChild; nChild=parent<<1; }}/*1.首先将待排序的元素构建二叉堆2.执行删除操作,并不真正删除,把头结点与尾节点交换,并形成新的堆3.重复步骤2*/void heapSort(int *arr)//堆排序{ int len=arr[0],i=arr[0]; while(--i) { delete_root(arr); printf("arr[0]:%d\n",arr[0]); } arr[0]=len;}int main(int argc,char **args){ int arr[30]={0,9,88,23,45,9,100,200,230,234,453,12}; int i=0; buildHeap(arr,10); insert(arr,2); for(i=0;i<=arr[0];i++) { printf("%d ",arr[i]); } //printf("%d\n",delete_root(arr)); printf("\n"); heapSort(arr); for(i=0;i<=arr[0];i++) { printf("%d ",arr[i]); } printf("\n"); return 0;}
- heap 堆
- heap 堆
- 堆(heap)
- 堆(heap)
- Heap 堆
- 堆 (heap)
- 堆heap
- 堆---heap
- 堆 Heap
- Heap【堆】
- 堆(heap)
- 堆 heap
- 堆 (heap)
- 堆--堆排序--heap--heap_sort
- 堆(Heap)AS3版
- InsideJVM(4)-Heap(堆)
- 堆排序(Heap Sort)
- 斜堆(Skew Heap)
- 【p3745】[六省联考2017]期末考试
- 使用 qemu 搭建内核开发环境
- Android 布局属性值
- Spring的事物传播行为
- JavaScript 面向对象(三)对象的方法及函数的上下文
- 堆 heap
- bzoj4012开店 动态点分治
- linux中IO复用(select,poll,epoll)
- 嵌套循环-九九乘法表-菱形打印
- Spring(一)Spring框架基础概念
- Linux学习(八):shell脚本编程
- 数学之对偶问题
- 文章标题
- JDK配置