红黑树

Red-Black Tree 的Java实现

拟墨画扇 提交于 2020-05-04 05:57:28
Every node is either red or black. The root is black. Every leaf (NIL) is black. If a node is red, then both its children are black. For each node, all paths from the node to descendant leaves contain the same number of black nodes. 上面是算法导论对红黑树性质的描述,这两天趁着不那么忙又比较无聊研究了一下,顺便用Java实现并简单进行了测试。算法不再赘述,只说说自己理解。 红黑树的核心在于进行普通BST的插入删除操作后对树结构的调整以维持红黑树的特性。 在插入操作中,设定新插入的节点为红色,这是为了不改变该节点所在路径的Black Height。但是新节点可能会与它的父节点同为红色,这会与性质4冲突(原树为空导致性质2不满足的情况比较简单,略过不提)。插入后的调整操作就是要在保持其他性质的前提下消除与性质4的冲突。由于新插入的节点x与x.p都是红色,则x.p.p一定为黑色,此时根据x.p.p的另一个孩子(x的uncle)的颜色分了两种情况:第一种即为case 1;第二种有根据x是x.p的左节点还是右节点分为case 2和case 3

常见数据结构(二)-树(二叉树,红黑树,B树)

醉酒当歌 提交于 2020-05-04 05:56:55
常见数据结构(二)-树(二叉树,红黑树,B树) 标签: algorithms [TOC] 本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程 《Algorithms, Part I》 中的Slides 相关命题的证明可参考 《算法(第4版)》 源码可在 官网 下载,也可以在我的github仓库 algorithms-learning 下载,已经使用maven构建 仓库下载: git clone git@github.com:brianway/algorithms-learning.git Binary Search Tree(二分查找树) 定义:A BST is a binary tree in symmetric order . A binary tree is either: Empty. Two disjoint binary trees (left and right). Symmetric order.Each node has a key, and every node’s key is: Larger than all keys in its left subtree. Smaller than all keys in its right subtree. 在java的实现中,每个节点

数据结构TIRE 树实际应用----过滤禁词

二次信任 提交于 2020-04-08 12:27:27
二叉树也是 递归 定义的,其结点有左右子树之分: (1) 完全二叉树 ——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有 叶子结点 ,并且叶子结点都是从左到右依次排布,这就是 完全二叉树 。 (2) 满二叉树 ——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。 (3) 深度——二叉树的层数,就是高度。 1、二叉树的存储结构 (1)顺序存储结构(适合完全二叉树和满二叉树) (2)链式存储结构(适合非完全二叉树) 2、二叉树的遍历 (1)递归遍历(中序遍历、先序遍历、后序遍历) (2)非递归遍历(利用堆栈实现) 3、二叉树的拓展 (1)线索二叉树(在节点空指针域存放前驱和后继节点的指针,加上线索标志域区分是线索指针还是child指针;建立线索二叉树,实质上就是遍历一颗二叉树,在相应的指针域进行操作) (2)二叉排序树(了解生成过程) (3)最优二叉树(哈夫曼树):对于一组有确定权值的叶子节点,构造的具有最小带权路径长度的二叉树(典型应用:哈夫曼编码) (3)平衡树: 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。(防止退化为链表,提高搜索效率) (4)红黑树:红黑树是平衡二叉树的一种;它有很好的性质,树中的结点都是有序的,而且因为它本身就是平衡的

对AVL树和红黑树的个人理解

萝らか妹 提交于 2020-04-08 10:48:10
都说编程算法很重要,可真没见几个.NET程序员研究算法的。这些日子非主流地研究了一些小算法,红黑树和AVL树算是其中复杂的了,但实际也就二三百行代码。悲催的是,网上根本找不到C#的理想版本(包括国外网站),寥寥几个,要么有错,要么非主流的实现方式。 所谓主流方式,就是用表二叉排序树节点TreeNode类的属性,除了左右子节点和值,还包括父节点。 /// <typeparam name="T">Type of the node.</typeparam> /// <typeparam name="K">Type of the node value.</typeparam> class TreeNode<T,K> where T:TreeNode<T,K> where K: IComparable<K> { public T LeftChild { get; set; } public T RightChild { get; set; } public T Parent { get; set; } public K Value { get; set; } } 不同二叉排序树间,为了保证查找性能,在插入和删除时,有不同的调整步骤。表示二叉排序树用抽象类Tree,我们可以把插入和删除节点做成内部虚方法,供公共方法调用(参数是要添加或删除的值)。 比如删除: public bool

跳表

情到浓时终转凉″ 提交于 2020-04-07 14:49:56
数据结构,跳表。跳表是redis的一个核心组件,也同时被广泛地运用到了各种缓存地实现当中,它的主要优点,就是可以跟红黑树、AVL等平衡树一样,做到比较稳定地插入、查询与删除。理论插入查询删除的算法时间复杂度为O(logN)。 什么是跳表 链表,相信大家都不陌生,维护一个有序的链表是一件非常简单的事情,我们都知道,在一个有序的链表里面,查询跟插入的算法复杂度都是O(n)。 我们能不能进行优化呢,比如我们一次比较两个呢?那样不就可以把时间缩小一半? 同理,如果我们4个4个比,那不就更快了? 跳表就是这样的一种数据结构,结点是跳过一部分的,从而加快了查询的速度。跳表跟红黑树又有什么差别呢?既然两者的算法复杂度差不多,为什么Redis要使用跳表而不使用红黑树呢?跳表相对于红黑树,主要有这几个优点:1.代码相对简单,手写个跳表还有可能,手写个红黑树试试? 2.如果我们要查询一个区间里面的值,用平衡树可能会麻烦。这里的麻烦指的是实现和理解上,平衡二叉树查询一段区间也是可以做到的。3.删除一段区间,这个如果是平衡二叉树,就会相当困难,毕竟设计到树的平衡问题,而跳表则没有这种烦恼。好了,相信你对跳表已经有一些认识了,我们来简单介绍平衡二叉树的几个基本操作。 查询 假如我们要查询11,那么我们从最上层出发,发现下一个是5,再下一个是13,已经大于11,所以进入下一层,下一层的一个是9,查找下一个

[ C++ STL ] STL中的unordered_map

和自甴很熟 提交于 2020-04-06 12:12:21
咳咳 在学校就不好好学C++ 现在惨了吧 啥也不会 好 那么来补充一下关于unordered_map的一些简单操作吧 定义 它叫做:无序映射。 C++ STL中的unordered_map实现使用了哈希表,在O(1)的时间实现对元素的查找,但是相应地在空间的开销增大了。 一些资料上比较了它和map的特点,我这C++还抓瞎的崽,暂时不进行拓展了,红黑树的特点我还没看呢... STL中的map对应的数据结构是红黑树,红黑树内的数据时有序的,在红黑树上查找的时间复杂度是O(logN),相对于unordered_map的查询速度有所下降,但额外空间开销减小。 常用函数 声明 #include <unordered_map> using namespace std; // <.., ..> 中指明两个变量类型,key-value unordered_map<string, int> map; 容器大小 cout << map.empty() << endl; cout << map.size() << endl; 插入键值对 map['A'] = 1; // or map.insert(make_pair('A', 1)); 判断key值是否存在 假设我们要检验 'B' 是否在我们刚刚声明的map中,可以用unordered_map的成员函数:find()函数和end()函数。

学习数据结构的第九天(二)(包括有一些还未解决的树的基本知识的问题)

白昼怎懂夜的黑 提交于 2020-04-05 18:43:01
先插入一些关于树的有关知识,完美二叉树,完全二叉树等,为之后学习AVL树,红黑树做点准备。 未解决: 问题1:如何用avl实现其他的数据结构 问题2:如果是avl树旋转了的话,那么搜索等结构还怎么做呢?就不再是小于走left,大于走right了吗? 问题3:红黑树的具体实现和目的 问题4:关于各种排序的时间复杂度以及排序。 先引入关于树的知识: 添加一个:度为0的节点和度为2的节点的关系是什么? 能够回答这17个问题是关键。 (1) 2的i次方个 (相当于等比数列) (2) Key:这里也就是等比数列求和,求和的意思是:前n项和,因为从0开始的时候,已经是1项了,所以是n+1项 (3)度:结点的子树个数(就是说:某个节点的度 不然就是0 不然就是1 不然就是2) 度分为节点的度和树的度,树的度:意思是所有节点的最大的度 key:也就是注意概念:节点的度和树的度的区别,节点的XX和树的XX,树一般作为统计概念,统计其中最大的 (4)入度和出度是什么概念,入度和出度是图的概念,树是度的概念。 这里讲的是节点V0的入度是2,出度是1. 入V0和出V0,记住,节点的度就是它的子树的个数就对了。 (5)二叉树,每个节点的子树最多有两颗,就是二叉树。 key:因为树的度是2,所以意思是最大的话是2. (6)完全二叉树 完美二叉树 意思是:完全二叉树可以最后一层 不完全

redis问学(一)

ε祈祈猫儿з 提交于 2020-04-05 16:38:04
一、主从复制 1. redis主从机制了解么?怎么实现的? 答: 二、数据结构 1. Redis熟悉么,了解哪些数据结构? 答: 2. 红黑树了解么,时间复杂度?既然两个数据结构时间复杂度都是O(logN),zset为什么不用红黑树? 答: 来源: https://www.cnblogs.com/chendf/p/12636621.html

STL容器的适用情况

荒凉一梦 提交于 2020-04-03 22:05:39
转自 http://hsw625728.blog.163.com/blog/static/3957072820091116114655254/ /*--> */ /*--> */ 一.各种容器的特性 vector 典型的序列容器, C++ 标准严格要求次容器的实现内存必须是连续的,唯一可以和标准 C 兼容的 stl 容器,任意元素的读取、修改具有常数时间复杂度,在序列尾部进行插入、删除是常数时间复杂度,但在序列的头部插入、删除的时间复杂度是 O(n) ,可以 在任何位置插入新元素,有随机访问功能,插入删除操作需要考虑。 deque 序列容器,内存也是连续的,和 vector 相似,区别在于在序列的头部插入和删除操作也是常数时间复杂度 , 可以 在任何位置插入新元素,有随机访问功能。 list 序列容器,内存是不连续的,任意元素的访问、修改时间复杂度是 O(n) ,插入、删除操作是常数时间复杂度 , 可以 在任何位置插入新元素。 set 关联容器,元素不允许有重复,数据被组织成一棵红黑树,查找的速度非常快,时间复杂度是 O(logN) multiset 关联容器,和 set 一样,却别是允许有重复的元素,具备时间复杂度 O(logN) 查找功能。 map 关联容器,按照 { 键,值 } 方式组成集合,按照键组织成一棵红黑树,查找的时间复杂度 O(logN) ,其中键不允许重复。

java集合之Map接口

时光怂恿深爱的人放手 提交于 2020-04-02 05:12:51
一、Map的实现类大概结构: ---Map:双列数据,存储key-value对的数据(类似于高中的函数)   ---HashMap:作为Map的主要实现类;线程不安全,效率高。可以存储null的key和value     ---LinkedHashMap:作为HashMap的子类,保证在遍历map元素时,可以按照添加的顺序实现遍历。因为它在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个。对于频繁的遍历操作,此类执行效率高于HashMap。   ---TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序。底层使用红黑树。   ---Hashtable:作为古老的实现类,比Map还早,1.0就有。线程安全的,效率低。不可以存储null的key和value。     ---Properties:常用来处理配置文件。key和value都是String类型 HashMap的底层:数组+链表(JDK7.0及之前)          数组+链表+红黑树(JDK8.0) 二、Map结构的理解: Map中的key:无序的、不可重复的,使用set存储所有的key。——>key所在类要重写equals()和hashCode()。 Map中的value:无序的、可重复的,使用Collection存储所有的value。——