- 浏览: 123015 次
- 性别:
- 来自: 上海
最新评论
与2-3-4树 相似,2-3 平衡树是一种搜索树。
但由于每个节点最多有两个数据,分裂算法需要新插入数据的参与,这导致算法与2-3-4树 有一定的差异。
每个节点可能会有2,3,4个子节点,对应可能会有1,2,3个数据。子节点数=数据数 + 1,不可能有空节点。 插入数据时,树向下遍历以得到恰当的叶子节点时,数据均插入叶子节点,如果子节点需要分裂,则进行节点分裂,分裂产生的新数据向父节点插入,如果父节点是满的,则向上递归调用此过程。当根节点分裂,所有叶子节点的层高都增加一层,以此原理来保证树的平衡。因为分裂需要第三个数据,所以是在插入之后分裂节点的,这与2-3-4树 的插入算法不同,此处采用添加临时数据,临时子节点的做饭以简化算法。但每个节点需要额外的空间来保存临时数据,临时子节点。
与2-3-4树 不同,分裂的主体算法移至Node,这样编程相对简单。其他的平衡数可以参见红黑树
此树没有实现删除数据的算法,如果需要,可考虑将数据标志为作废的方式,以避免真正的删除时的复杂。 插入的数据为了简便起见,假设均为Integer,且不会重复。
方法ordinal是升序打印,为的是测试。
Tree.main 函数提供一个简短的测试。
class Node { private Integer[] values = new Integer[3]; //装数据 private Node[] children = new Node[4]; //装子节点 private Node parent; private int size; //当前的有效数据的个数 Node() {} Node(Integer value) { values[0] = value; size++; } Node getParent() { return parent; } int find(Integer value) { //得到当前节点下要查找的数据的下标索引 for(int i=0; i<size; i++) if(values[i].equals(value)) return i; return -1; } Node getNextChild(Integer value) { //在当前的节点下根据关键数值查找合适的子节点 for(int i=0; i<size; i++) if(value < values[i]) return children[i]; return children[size]; } Node getChild(int index) { return children[index]; } boolean isLeaf() { return children[0] == null; } boolean needSplit() { return size > 2; } //返回当前节点是否需要分裂 int size() { return size; } Integer getValue(int index) { return values[index]; } int insert(Integer value) { //将数据插入当前节点的恰当位置,以保持数据的升序排序 int pos = size ; while(pos > 0 && values[pos -1 ] > value) { values[pos] = values[pos-1]; pos--; } values[pos] = value; size++; return pos; } void insertChild(int index, Node child) { //在指定的位置之后插入子节点,之后的子节点依次向后移动 for(int i=size; i>index + 1; i--) children[i] = children[i-1]; children[index + 1] = child; if(child != null) child.parent = this; } Node disConnect(int index) { //断开指定位置的子节点 Node result = children[index]; if(result != null) result.parent = null; children[index] = null; return result; } void connect(int index, Node child) { //在指定位置连接子节点 children[index] = child; if(child != null) child.parent = this; } Node split() { assert needSplit(); Node left = this; //左节点 Integer middle = values[1]; //中间数值,将要提升至父节点 Node right = new Node(values[2]); //右节点 //调整左节点中的数据与有效数据大小 left.values[1] = null; left.values[2] = null; left.size = 1; //如果没有父节点(此时当前节点一定为根节点),则创建新的父节点 if(parent == null) { parent = new Node(middle); parent.connect(0,left); parent.connect(1,right); } else { //否则在父节点中插入要提升的数值,并将新的子节点放入插入合适的位置 int index = parent.insert(middle); parent.insertChild(index,right); } if(!isLeaf()) { //当前节点有子节点,则将子节点平分至两个分裂后两个新节点中 Node child1 = disConnect(2); Node child2 = disConnect(3); right.connect(0,child1); right.connect(1,child2); } return parent; } } class Tree { private Node root = new Node(); //根节点 void insert(Integer value) { Node current = root; //从根节点开始寻找恰当的叶子节点 while(!current.isLeaf()) current = current.getNextChild(value); current.insert(value); //将数值插入叶子节点 if(current.needSplit()) split(current); //如果需要,则分裂叶子节点 } void ordinal() { ordinal(root); //打印 } private void ordinal(Node node) { //按照升序遍历并打印数据 for(int i=0; i<node.size(); i++) { if(!node.isLeaf()) ordinal(node.getChild(i)); System.out.println(node.getValue(i)); } if(!node.isLeaf()) ordinal(node.getChild(node.size())); } boolean contains(Integer value) { //判断树中是否包含指定的关键值的字段 Node current = root; while(!current.isLeaf()) { if(current.find(value) != -1) return true; else current = current.getNextChild(value); } return current.find(value) != -1; } private void split(Node node) { Node parent = node.split(); //分裂当前的节点,并得到其父节点 if(node == root) root = parent; //如果当前节点是根节点,则重置根结点 if(parent.needSplit()) split(parent); //如果父节点需要分裂,则递归调用 } public static void main(String[] args) { Tree t = new Tree(); t.insert(50); t.insert(51); t.insert(52); t.insert(53); t.insert(54); t.insert(55); t.insert(56); t.insert(57); t.insert(17); t.insert(87); t.insert(27); t.insert(67); t.insert(97); t.ordinal(); assert t.contains(67); assert t.contains(17); assert !t.contains(100); } }
发表评论
-
Tree 红黑树
2008-05-01 17:23 2705红黑树是一种二叉平衡 ... -
Tree 2-3-4 平衡搜索树
2008-04-20 10:53 35012-3-4 平衡树是一种搜索树。每个节点可能会有2,3,4个子 ... -
Graph 图-邻接表法
2008-04-17 00:08 3008用邻接表法表示的双向图(改单向容易,只要修改connect,d ... -
Graph 图-邻接矩阵法
2008-04-16 22:56 3546用邻接矩阵法表示的双向图(改单向容易,只要修改connect, ... -
Heap 堆
2008-04-16 00:28 1482这里的堆不是java中内存分配的堆。只是一种数据结构。 堆是二 ... -
HashTable 基于链表地址法
2008-04-15 00:49 1651功能上于前面两个HashTable(-) ,HashTable ... -
HashTable 基于开放地址法(二)
2008-04-14 19:40 2024与前一个HashTable 基本相同(方法说明请参照它),只是 ... -
HashTable 基于开放地址法
2008-04-13 22:59 1594该HashTable基于定常数组的开放地址法,搜索时采用线性探 ... -
Tree 二叉搜索树
2008-04-11 00:03 1721每个节点最多两个子节点,其中左边节点的值小于该节点的值,右边节 ... -
PriorityQueue 优先级队列
2008-04-06 17:57 3453提供一个基于链表的优先级队列,为了简便,只存储整数,假设数值越 ... -
PriorityQueue 优先级队列
2008-04-06 16:57 4351提供一个基于定长数组的优先级队列,为了简便,只存储整数,假设数 ... -
Queue 队
2008-04-06 13:36 1560指定最大值的队,底层用数组实现构造函数:指定最大容量put:放 ... -
ArrayStack 栈
2008-04-06 12:00 1308用Array实现的栈结构,功能与LinkedStack一致编程 ... -
Array 可变长可变维数组
2008-04-06 11:25 1844一个可以变长,变维的数组(只可以变大),用来替代多维数组基本做 ... -
StackDLink 双向链表
2008-04-05 23:20 1155用LinkedStack实现的双向链表,功能与DLink一致就 ... -
LinkedList 列表
2008-04-05 19:16 1466列表的简单实现,只能存储非负整数List 也属于ADT(抽象数 ... -
ArrayList 列表
2008-04-05 19:01 1209列表的简单实现,只能存储非负整数List 也属于ADT(抽象数 ... -
LinkedQueue 队
2008-04-05 18:43 1857实现了队的最简单功能:先进现出队属于ADT(抽象数据类型),其 ... -
DLink 双向双端链表
2008-04-05 18:06 1506DLink 实现一个简单的双向双端链表与Link一样,假定其之 ... -
LinkedStack 栈
2008-04-05 17:45 1128LinkedStack栈属于ADT(抽象数据类型),其提供同样 ...
相关推荐
通过分析"2-3-tree-master.zip"的代码,我们可以深入理解2-3树的各种操作的实现细节,例如节点的创建、插入、删除和查找方法,以及树的平衡调整策略。这些实现可以帮助我们更好地应用和优化这种数据结构。
搜索操作在2-3树中的进行方式与普通二叉搜索树非常相似。插入或删除操作的执行需要描述的是如何更新内部节点存储的键的副本,但这部分细节比较直接明了,这里就留给读者自己探究。 插入操作开始于执行一个搜索,以...
B-Tree(B树),是一种自平衡的树数据结构,它能够保持数据排序,常用于数据库和文件系统中。B-Tree的主要特性是节点可以拥有多个子节点,通常远多于二叉树。这种数据结构允许高效地在大型数据集上进行查找、插入和...
总而言之,从AVL树到2-3树,再到2-3-4树,自平衡树结构展现了从二叉搜索树到多路搜索树的演进,每一步都体现了提高数据操作效率和优化树平衡的不懈追求。它们通过严格的平衡机制和精心设计的节点分裂与旋转规则,...
在给定的压缩包文件"2-3-tree-master"中,很可能包含了C++实现2-3树的源代码。这个代码库可能包括了节点类的定义、插入、查找和删除等操作的实现,以及相关的测试用例,帮助用户理解和学习2-3树的工作原理。 通过...
二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树数据结构,它具有以下特性: 1. **每个节点都包含一个键(key)、一个关联的值、一个指向左子节点的引用和一个指向右子节点的引用**。 2. **键的值大于左...
相比于普通二叉排序树,2-3查找树在插入新节点时能更好地保持平衡,减少了深度过深的情况,从而提高了性能。 在实现2-3查找树的过程中,我们需要处理各种边界情况。例如,插入一个新节点时,如果树为空,新节点就是...
二叉搜索树(BST,Binary Search Tree)是一种特殊类型的二叉树,它的每个节点都包含一个键值,且满足以下特性: 1. 节点的左子树中所有键值都小于该节点的键值。 2. 节点的右子树中所有键值都大于该节点的键值。 3...
3. **删除**:kd树的删除操作相对复杂,因为可能需要重新平衡树结构,通常在实际应用中不常用。 4. **分割**:在构建kd树时,选择最优分割维度和位置以最大化子区域间的差异性,这有助于提高搜索效率。 kd树在许多...
2-3树是平衡搜索树的一种形式,类似于二叉树,其中某些节点具有2个密钥和3个子代,而不是仅1个密钥和2个子代。 为了实现,我们不是每个节点都有可变数量的键,而是创建一个红黑树:一个二进制树,其中的节点可以被...
在提供的文件列表中,"SplayTree"可能是指伸展树(Splay Tree),这是一种自调整的二叉搜索树,每次访问节点时都会将其移动到根位置,以优化后续访问。这种数据结构在访问模式具有局部性时表现良好,但并不保证总体...
【描述】提到了其中包含的“超级经典算法”,暗示了我们将探讨的算法包括但不限于二叉查找树(Binary Search Tree, BST)、AVL树、红黑树(Red-Black Tree)、B树、Trie树以及平衡二叉搜索树等。 1. **二叉查找树...
对于有序二叉树(如二叉搜索树),从根节点开始,如果目标值小于当前节点,则在左子树中继续搜索;反之,在右子树中搜索。 4. **删除节点**: 删除节点是最复杂的操作之一,因为它可能涉及重新排列子树。根据要...
3. **时间复杂度**:由于红黑树的自平衡性质,插入、删除和查找操作的时间复杂度都是O(log n),其中n是树中的节点数。这使得红黑树在处理大量数据时表现优秀。 4. **应用**:红黑树在多种场景下被广泛使用,如C++ ...
节点间隔树基于二叉搜索树(Binary Search Tree, BST)的概念,但每个节点不仅包含一个值,还包含一个区间。这种数据结构的设计使得在O(log n)的时间复杂度内完成区间查询、插入和删除操作成为可能。区间查询能够...
在二叉树的实现中,常见的数据结构包括二叉搜索树(BST)、完全二叉树、满二叉树、平衡二叉树(如AVL树和红黑树)等。每个都有其特定的性质和操作,如插入、删除、查找等。C语言实现这些操作时,需要考虑指针的使用...
查找操作在二叉搜索树中尤为高效,因为它满足左子树的所有节点值小于根节点,右子树的节点值大于根节点,这使得查找可以在对数时间内完成。插入和删除操作则需要维护树的平衡,以防止退化成链表,降低效率。常见的...
2-3树在实际应用中主要用于数据库索引、文件系统等场景,它的优点在于插入和删除操作通常比二叉搜索树更快,因为它始终保持平衡。然而,与红黑树、AVL树等其他自平衡树相比,2-3树在实际编程中可能不太常见,因为...
1. **B-树结构**:B-树是一种自平衡的多路搜索树,每个节点可以有多个子节点,这些子节点通常称为分支或指针。B-树的每个节点包含一个键值集合和对应的子树指针集合。 2. **度**:B-树的度指的是每个节点最多能有的...
平衡搜索树是一种特殊的二叉搜索树,其设计目标是为了在最坏的情况下也能保持较高的搜索效率,不至于因为树的不平衡而导致性能显著下降。在平衡搜索树的诸多变种中,红黑树是一种广泛使用的数据结构,它通过在节点中...