完全二叉树,堆,堆排序,优先队列
2015-11-25 21:19
399 查看
完全二叉树
1、定义:对树中结点从上到下从左到右顺序进行编号,且编号为i的结点与完美二叉树中编号为i的结点在二叉树中位置相同。
2、完全二叉树的特点:
(1) 叶结点只能出现在下层和次下层且最下层的叶子结点出现在树的左部。
(2) 由特性,适合以数组的形式进行存储,并且父节点和左右儿子有一定关系便于访问。
(3) 当以数组形式存储n个元素时,叶结点下标分别是 [n/2]+1 [n/2]+2……n。即叶结 点个数为n/2个。
(4) 具有n个结点的完全二叉树深度为 k = lgn上取整。(根节点深度为1)高度 k = lgn(下取整)
(5) 在高度为h的完全二叉树中元素个数 2^(h ). <= n <= 2^(h+1)- 1 (叶结点高度为0),在高度为h的完全二叉树中元素个数 2^(h -1 )<= n <= 2^(h)- 1
(6) 在一个含有n个元素的完全二叉树中,至多有(n/ 2 ^(h+1))向上取整 个高度为h的结点。 至多有 2^(h-1)个 深度为h的结点。
(7) 在完全二叉树中 n0 = n2 + 1, n = 2 * n0 - 1 + 1 或者 n = 2 * n0 - 1 取决于
叶结点是偶数还是奇数。
堆
堆是一种特殊的完全二叉树。
1 结构性:(二叉)堆是一个数组,他可以被看成一个完全二叉树。
2.有序性:从任意一个点顺着路径到另一个点关键字权值总是非递增或者非递减的
兄弟之间并不存在特定的约束关系。当为最小堆时,满足 A[PARENT(i)] <= A[i]。
对于一个最大堆 , 最大的元素在树根处, 最小的元素在叶结点中。
以最大堆为例:
一、维护堆的性质:
1、下渗: 0 (lg n)
前提 LEFT(i) 和 RIGHT(i) 子树 必须为最大堆。
2、上渗: 0 (lg n)
满足 在该层i左边的所有元素以及上多层的元素都满足堆的性质。
二、建堆:
1、用下渗方法建堆0(lgn)
用上渗方法建堆:0(lgn)
堆排序:0(nlgn)
堆排序时间复杂度为0(nlgn)空间复杂度为0(1)但是不稳定的。
优先队列
一、增加一个元素:
由于在堆中增加一个元素,所以可以用想上渗透来维持堆的性质
二、删除:
在删除时,要明确在执行上渗或下渗时堆的大小(减一)
1、删除顶部元素:
2、删除某个元素:
向上渗透的办法:
现将这个元素变大使得上移到顶部,用DeleteTop(H);删除。
1、定义:对树中结点从上到下从左到右顺序进行编号,且编号为i的结点与完美二叉树中编号为i的结点在二叉树中位置相同。
2、完全二叉树的特点:
(1) 叶结点只能出现在下层和次下层且最下层的叶子结点出现在树的左部。
(2) 由特性,适合以数组的形式进行存储,并且父节点和左右儿子有一定关系便于访问。
#define LEFT(i) (i*2) #define RIGHT(i) (i*2+1) #define PARENT(i) (i/2)
(3) 当以数组形式存储n个元素时,叶结点下标分别是 [n/2]+1 [n/2]+2……n。即叶结 点个数为n/2个。
(4) 具有n个结点的完全二叉树深度为 k = lgn上取整。(根节点深度为1)高度 k = lgn(下取整)
(5) 在高度为h的完全二叉树中元素个数 2^(h ). <= n <= 2^(h+1)- 1 (叶结点高度为0),在高度为h的完全二叉树中元素个数 2^(h -1 )<= n <= 2^(h)- 1
(6) 在一个含有n个元素的完全二叉树中,至多有(n/ 2 ^(h+1))向上取整 个高度为h的结点。 至多有 2^(h-1)个 深度为h的结点。
(7) 在完全二叉树中 n0 = n2 + 1, n = 2 * n0 - 1 + 1 或者 n = 2 * n0 - 1 取决于
叶结点是偶数还是奇数。
堆
堆是一种特殊的完全二叉树。
1 结构性:(二叉)堆是一个数组,他可以被看成一个完全二叉树。
2.有序性:从任意一个点顺着路径到另一个点关键字权值总是非递增或者非递减的
兄弟之间并不存在特定的约束关系。当为最小堆时,满足 A[PARENT(i)] <= A[i]。
对于一个最大堆 , 最大的元素在树根处, 最小的元素在叶结点中。
以最大堆为例:
一、维护堆的性质:
1、下渗: 0 (lg n)
前提 LEFT(i) 和 RIGHT(i) 子树 必须为最大堆。
void PercolateDown(MaxHeap H,Position i)//下滤 { if(H == NULL) return ; //从左右孩子和父母中找到最大的 int L = LEFT(i), R = RIGHT(i), larget; //同时处理了只有一个左子树和没有儿子的这两种特殊情况 if(L <= H->size && H->array[L] > H->array[i]) larget = L; else larget = i; if(R <= H->size && H->array[R] > H->array[larget]) larget = R; //如果这个最大值为父母 找到位置 停止递归 if(larget != i) { EXCHANGE(H->array[larget],H->array[i]); PercolateDown(H, larget); } return ; }
2、上渗: 0 (lg n)
满足 在该层i左边的所有元素以及上多层的元素都满足堆的性质。
void PercolateUp(MaxHeap H,Position i)//上滤 { if(H == NULL) return ; //与其父母比较 是否交换,直到找到位置为止 while(i > 1 && H->array[i] > H->array[PARENT(i)] ) { EXCHANGE(H->array[i],H->array[PARENT(i)]); i = PARENT(i); } }
二、建堆:
1、用下渗方法建堆0(lgn)
void BuildMaxHeap(MaxHeap H) { if(H == NULL) return ; int i = H->size/2; while(i>=1) { PercolateDown(H,i); i--; } }
用上渗方法建堆:0(lgn)
void BuildMaxHeap(MaxHeap H) { if(H == NULL) return ; int i =1; while(i<=H->size) { PercolateUp( H, i); i++; } }
堆排序:0(nlgn)
void HeapSort(MaxHeap H) { if(H == NULL) return ; int i = H->size; BuildMaxHeap(H); // 建好堆 while(i>=2) { EXCHANGE(H->array[1],H->array[H->size]); H->size--; PercolateDown(H,1); i--; } }
堆排序时间复杂度为0(nlgn)空间复杂度为0(1)但是不稳定的。
优先队列
一、增加一个元素:
由于在堆中增加一个元素,所以可以用想上渗透来维持堆的性质
void Insert(MaxHeap H,ElementType item) { if(H == NULL) return ; H->array[++H->size] = item; H->printSize++; PercolateUp(H,H->size); }
二、删除:
在删除时,要明确在执行上渗或下渗时堆的大小(减一)
1、删除顶部元素:
ElementType DeleteTop(MaxHeap H) { if(H == NULL) return 0 ; ElementType item = H->array[1]; H->array[1] = H->array[H->size]; H->size--; // 位置不能出现在下一句之后 否则 还是在原来的堆中进行维护 PercolateDown(H,1); return item; }
2、删除某个元素:
向上渗透的办法:
现将这个元素变大使得上移到顶部,用DeleteTop(H);删除。
void IncreaseKey(MaxHeap H,Position X,int increaseItem) { if(H == NULL) return ; H->array[X] -=increaseItem; PercolateUp(H,X); } void Delete(MaxHeap H,Position X) { if(H == NULL) return ; IncreaseKey(H,X,MAX); DeleteTop(H); }
***************************************** 向下渗透: //不成立 因为 当最后一个结点位于另一个子树中而删除的结点在别的子树中这样破坏堆。 void Delete(MaxHeap H,Position X) { if(H == NULL) return ; H->array[X] = H->array[H->size]; H->size--; PercolateDown(H,X); }**************************************
相关文章推荐
- stm32 启动代码startup_stm32f10x_hd.s注解
- c 冒泡排序
- 两种链表的合并运算(一种带头结点的,一种不带头结点)
- 没有躲过的坑--有if就要有else(一定成对)
- postgresql数据库三种删除重复数据的方法
- Hadoop2.6.0学习笔记(三)HDFS架构
- [Web前端]梳理-DOM.2. 节点树.4.节点信息
- 如何使用lldb/gdb调试Nim程序
- 没有躲过的坑--有if就要有else(一定成对)
- 自定义一个退出AlertDialog(对话框)
- Net开源工作流Roadflow的使用与集成
- 算法 之 栈的简单讲解
- 慕课网JavaScript编程练习
- NULL与空字符串的区别(以JAVA为例)
- 问题之~The following packages have unmet dependencies: openssh
- 神经网络(6)---一些神经网络学习复杂非线性问题的例子(2)
- phpstorm快捷键
- 可持久化线段树求区间第k大
- 基于Verilog HDL的有限状态机
- linux搭建ftp服务器