叶子结点

线段树(segment tree)

自闭症网瘾萝莉.ら 提交于 2020-01-26 15:41:31
这是从网上看到的两篇博客感觉挺好的就转过来,留作复习的材料。 转载来源:http://www.cnblogs.com/superbin/archive/2010/08/02/1790467.html 线段树(interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式。 上图是一棵典型的线段树,它对区间[1,10]进行分割,直到单个点。这棵树的特点 是: 1. 每一层都是区间[a, b]的一个划分,记 L = b - a 2. 一共有log2L层 3. 给定一个点p,从根到叶子p上的所有区间都包含点p,且其他区间都不包含点p。 4. 给定一个区间[l; r],可以把它分解为不超过2log2 L条不相交线段的并。 其中第四点并不是很显然,图8.1显示了[2, 8]的分解方式,深灰色结点为分解后的 区间,浅灰色结点是递归分解过程中经过的结点。为了叙述方便,下面称树中的结点 所对应的区间为树中区间。   从第3点和第4点可以得出结论:修改一个点只用修改log2 L个树中区间信息,而统计一个区间只需要累加2log2 L个树中区间的信息,且访问的总结点数是O(log L)的。两个操作都很容易实现。   动态统计问题I 有一个包含n个元素的整数数组A,每次可以修改一个元素,也可以询问某一个区间[l; r]内所有元素的和。如何设计算法

线段树之入门篇

断了今生、忘了曾经 提交于 2020-01-26 15:40:07
线段树 (interval tree) 是把区间逐次二分得到的一树状结构。它反映了包含归并排序在内的非常多分治算法的问题求解方式。 上图是一棵典型的线段树。它对区间[1,10]进行切割。直到单个点。这棵树的特点 是: 1. 每一层都是区间[a, b]的一个划分。记 L = b - a 2. 一共同拥有log2L层 3. 给定一个点p。从根到叶子p上的全部区间都包括点p。且其它区间都不包括点p。 4. 给定一个区间[l; r],能够把它分解为不超过2log2 L条不相交线段的并。 当中第四点并非非常显然。图8.1显示了[2, 8]的分解方式,深灰色结点为分解后的 区间,浅灰色结点是递归分解过程中经过的结点。 为了叙述方便,以下称树中的结点 所相应的区间为树中区间。   从第3点和第4点能够得出结论:改动一个点仅仅用改动log2 L个树中区间信息。而统计一个区间仅仅须要累加2log2 L个树中区间的信息,且訪问的总结点数是O(log L)的。 两个操作都非常easy实现。    动态统计问题I 有一个包括n个元素的整数数组A,每次能够改动一个元素,也能够询问某一个区间[l; r]内全部元素的和。怎样设计算法,使得改动和询问操作的时间复杂度尽量低?   方法一 直接做, 则改动操作是O(1)的, 但询问须要进行累加, 时间复杂度为O(r ¡ l),最坏情况为O(n)。   方法二

线段树入门

♀尐吖头ヾ 提交于 2020-01-26 15:39:07
 // 转载自: http://www.cnblogs.com/superbin/archive/2010/08/02/1790467.html 感觉讲的很详细。也很实用。果断转~感谢楼主~~~ 线段树入门 线段树 (interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式。 上图是一棵典型的线段树,它对区间[1,10]进行分割,直到单个点。这棵树的特点 是: 1. 每一层都是区间[a, b]的一个划分,记 L = b - a 2. 一共有log2L层 3. 给定一个点p,从根到叶子p上的所有区间都包含点p,且其他区间都不包含点p。 4. 给定一个区间[l; r],可以把它分解为不超过2log2 L条不相交线段的并。 其中第四点并不是很显然,图8.1显示了[2, 8]的分解方式,深灰色结点为分解后的 区间,浅灰色结点是递归分解过程中经过的结点。为了叙述方便,下面称树中的结点 所对应的区间为树中区间。   从第3点和第4点可以得出结论:修改一个点只用修改log2 L个树中区间信息,而统计一个区间只需要累加2log2 L个树中区间的信息,且访问的总结点数是O(log L)的。两个操作都很容易实现。    动态统计问题I 有一个包含n个元素的整数数组A,每次可以修改一个元素,也可以询问某一个区间[l; r]内所有元素的和

哈夫曼树(最优二叉树)、哈夫曼编码

冷暖自知 提交于 2020-01-25 15:58:49
在此祝大家新年快乐,新的一年守住头发,不断进步! 哈夫曼树 一、哈夫曼树基本概念 二、哈夫曼树的构造算法 三、哈夫曼构造算法的实现 四、哈夫曼编码 五、哈夫曼编码的算法实现 一、哈夫曼树基本概念 (1) 路径 :从树中的一个结点到另一个结点之间的分支构成这两个结点之间的路径 (2) 路径长度 :路径上的分支数目称作路径长度。 (3) 树的路径长度 :从树根到每一结点的路径长度之和。 (4) 权 :将树中结点赋给一个有着某种含义的数值,则这个数值称为该 结点的权 。 (5) 结点的带权路径长度 :从 根结点 到该结点之间的 路径长度 与该结点的 权 的 乘机 (6) 树的带权路径长度 :树中所有 叶子结点 的 带权路径长度之和。 看以下几个例子: 我们可以总结出: 哈夫曼树:最优二叉树(带权路径长度(WPL)最短的二叉树) ,带权路径长度最短是在“度相同”的树中比较而得的结果,因此有最优二叉树、最优三叉树之称。 满二叉树不一定是哈夫曼树 哈夫曼树中权越大的叶子离根越近 具有相同带权结点的哈夫曼树不唯一 根据 权值越大的结点离根结点越近 这个特点,哈夫曼最早给出了一个构造哈夫曼树的方法,称为 哈夫曼算法 二、哈夫曼树的构造算法 典型的贪心算法:构造哈夫曼树时首先选择权值小的叶子结点。 哈夫曼算法(构造哈夫曼树的方法) (1)根据n个给定的权值{w1,w2,w3…,wn

《剑指offer》— JavaScript(24)二叉树中和为某一值的路径

断了今生、忘了曾经 提交于 2020-01-25 13:42:34
二叉树中和为某一值的路径 题目描述   输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 思路 前序遍历二叉树,每次更新当前路径的和curtSum; 判断当前结点是否是叶子结点,以及curtSum是否等于expectNumber。如果是,把当前路径保存在res结果中; 若不符合条件,则弹出此结点。 实现代码 /* function TreeNode(x) { this.val = x; this.left = null; this.right = null; } */ function FindPath(root, expectNumber) { var result = []; if (root === null) { return result; } dfsFind(root, expectNumber, [], 0, result); return result; } function dfsFind(root, expectNumber, path, currentSum, result) { currentSum += root.val; path.push(root.val); if (currentSum == expectNumber && root.left == null

Java实现堆排序

匆匆过客 提交于 2020-01-24 22:16:18
堆排序使用的是完全二叉树。 即满足r(n)的左孩子是r(2*n+1),右孩子是r(2*n+2)。 堆排序它首先将所有的元素添加到堆上,然后不断移除最大的元素并用最后一个叶子结点替换根节点之后再调整堆到大顶堆或者小顶堆的一种排序方法。底层是使用ArrayList进行存储元素的。 大顶堆的概念:即根节点是最大的(相对于左右孩子结点)元素 例如下面的图 小顶堆的概念:即根节点存储的是最小的(相对于左右孩子结点)元素 例如下面的图 大顶堆的排序示意图如下 示例数组 int[] arr = {3,2,1,4,5} 首先使将数组存储到自己的构造的堆中。 将根节点移除 并将末节点放到根节点的位置 并且重新开始调整堆 调整的过程 如此循环 代码实现 构造堆类 class Heap < E extends Comparable < E > > { private ArrayList < E > list = new ArrayList < > ( ) ; public Heap ( ) { } //从数组添加 public Heap ( E [ ] object ) { for ( int i = 0 ; i < object . length ; i ++ ) { add ( object [ i ] ) ; } } public void add ( E newObject ) { list .

B-Tree 和 B+Tree 结构及应用,InnoDB 引擎, MyISAM 引擎

為{幸葍}努か 提交于 2020-01-24 22:01:29
1.什么是B-Tree 和 B+Tree,他们是做什么用的? B-Tree是为了磁盘或其它存储设备而设计的一种 多叉平衡查找树 ,B-Tree 和 B+Tree 广泛应用于文件存储系统以及 数据库 系统中。 在大规模数据存储中,实现索引查询这样一个实际背景下,树节点存储的元素数量是有限的(如果元素数量非常多的话,树的高度就会增大,查找就退化成节点内部的线性查找了),这样导致二叉查找树结构由于 树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下 (为什么会出现这种情况?这跟外部存储器-磁盘的存储方式有关)。那么该如何减少树的高度呢?一个基本的想法就是:采用 多叉树 结构(每个节点存放多个元素,每个节点有多个子节点,这样树的高度就降低了)。根据平衡二叉树的启发,自然就想到平衡多路查找树结构。B-Tree的各种操作能使B-Tree保持较低的高度,从而达到有效避免磁盘过于频繁的查找存取操作,从而有效提高查找效率。 2.B-Tree 2.1定义 m阶B-Tree满足以下条件: 1、每个节点最多拥有m个子树 2、根节点至少有2个子树 3、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点) 4、所有叶子节点都在同一层 5、每个节点最多可以有m-1个key 6、每个节点中的key以升序排列 7、节点中key元素左节点的所有值都小于或等于该元素

B-Tree 和 B+Tree 结构及应用,InnoDB 引擎, MyISAM 引擎

烂漫一生 提交于 2020-01-24 14:11:00
1.什么是B-Tree 和 B+Tree,他们是做什么用的? B-Tree是为了磁盘或其它存储设备而设计的一种 多叉平衡查找树 ,B-Tree 和 B+Tree 广泛应用于文件存储系统以及数据库系统中。 在大规模数据存储中,实现索引查询这样一个实际背景下,树节点存储的元素数量是有限的(如果元素数量非常多的话,树的高度就会增大,查找就退化成节点内部的线性查找了),这样导致二叉查找树结构由于 树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下 (为什么会出现这种情况?这跟外部存储器-磁盘的存储方式有关)。那么该如何减少树的高度呢?一个基本的想法就是:采用 多叉树 结构(每个节点存放多个元素,每个节点有多个子节点,这样树的高度就降低了)。根据平衡二叉树的启发,自然就想到平衡多路查找树结构。B-Tree的各种操作能使B-Tree保持较低的高度,从而达到有效避免磁盘过于频繁的查找存取操作,从而有效提高查找效率。 2.B-Tree 2.1定义 m阶B-Tree满足以下条件: 1、每个节点最多拥有m个子树 2、根节点至少有2个子树 3、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点) 4、所有叶子节点都在同一层 5、每个节点最多可以有m-1个key 6、每个节点中的key以升序排列 7、节点中key元素左节点的所有值都小于或等于该元素

一步一步编写AVL树

送分小仙女□ 提交于 2020-01-24 06:57:31
第一步:定义结构体 typedef struct Node{ int d; //data int h=1; //height struct Node* l=NULL; struct Node* r=NULL; Node(int d=0):d(d){ } }Node; 这个结构体和常规的二叉树结构体很相似。但是不同的是多了个属性“h”(height)。用这个属性来记录结点的高度,叶子结点为1,空结点为0 。 第二部:编写BST树的插入函数 Node* insert(Node* p,int v){ Node * node=new Node(v); if(!p){ return node; } if(v < p->d){ //左子树 if(p->l){ p->l=insert(p->l,v); }else{ p->l=node; } }else{ if(p->r){ p->r=insert(p->r,v); }else{ p->r=node; } } // setHeight(p); //平衡旋转代码 //end of 平衡旋转代码 return p; } 第三步:编写高度获取与设置的辅助函数 高度获取: int getHeight(Node* node){ if(node) return node->h; //如果非空返回这个结点的height return 0; //空节点的高度是0

第二十一次-查找(二)

眉间皱痕 提交于 2020-01-24 01:33:32
折半查找 适用条件: Ø 线性表中的记录必须按关键码有序; Ø 必须采用顺序存储。 基本思想: 在有序表中(low, high,low<=high), 取中间记录作为比较对象, 若给定值与中间记录的关键码相等,则查找成功; 若给定值小于中间记录的关键码,则在中间记录的左半区继续查找; 若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。 不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。 int LineSearch :: BinSearch1(int k){ int mid, low = 1, high = length; //初始查找区间是[1, n] while (low <= high) {//当区间存在时 mid = (low + high) / 2; if (k < data[mid]) high = mid - 1; else if (k > data[mid]) low = mid + 1; else return mid; //查找成功,返回元素序号 } return 0; //查找失败,返回0 } int LineSearch :: BinSearch2(int low, int high, int k){ if (low > high) return 0; //递归的边界条件 else { int mid = (low + high) /