`
shenyu
  • 浏览: 122581 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Tree 2-3 平衡搜索树

阅读更多

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);

	}

}
 
8
0
分享到:
评论

相关推荐

    2-3-tree-master.zip_2-3树建立

    通过分析"2-3-tree-master.zip"的代码,我们可以深入理解2-3树的各种操作的实现细节,例如节点的创建、插入、删除和查找方法,以及树的平衡调整策略。这些实现可以帮助我们更好地应用和优化这种数据结构。

    2-3 tree (Introduction of Algorithm)

    搜索操作在2-3树中的进行方式与普通二叉搜索树非常相似。插入或删除操作的执行需要描述的是如何更新内部节点存储的键的副本,但这部分细节比较直接明了,这里就留给读者自己探究。 插入操作开始于执行一个搜索,以...

    B-Tree B-Tree

    B-Tree(B树),是一种自平衡的树数据结构,它能够保持数据排序,常用于数据库和文件系统中。B-Tree的主要特性是节点可以拥有多个子节点,通常远多于二叉树。这种数据结构允许高效地在大型数据集上进行查找、插入和...

    2-3-tree:2-3树数据结构的简单演示

    在给定的压缩包文件"2-3-tree-master"中,很可能包含了C++实现2-3树的源代码。这个代码库可能包括了节点类的定义、插入、查找和删除等操作的实现,以及相关的测试用例,帮助用户理解和学习2-3树的工作原理。 通过...

    資料結構2-3-4樹

    2-3树是另一种自平衡的多路搜索树,不同于二叉树,它允许每个内部节点有两个或三个子节点。2-nodes有两个子节点,而3-nodes有三个子节点。所有的叶子节点都位于相同的深度,保证了树的平衡。2-3树的搜索操作沿着键值...

    tree-java.rar_tree_二叉搜索树

    二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树数据结构,它具有以下特性: 1. **每个节点都包含一个键(key)、一个关联的值、一个指向左子节点的引用和一个指向右子节点的引用**。 2. **键的值大于左...

    CHAZHAO.zip_2-3查找树

    相比于普通二叉排序树,2-3查找树在插入新节点时能更好地保持平衡,减少了深度过深的情况,从而提高了性能。 在实现2-3查找树的过程中,我们需要处理各种边界情况。例如,插入一个新节点时,如果树为空,新节点就是...

    06-4.1 二叉搜索树-讲义.pptx

    二叉搜索树(BST,Binary Search Tree)是一种特殊类型的二叉树,它的每个节点都包含一个键值,且满足以下特性: 1. 节点的左子树中所有键值都小于该节点的键值。 2. 节点的右子树中所有键值都大于该节点的键值。 3...

    kdTree-master_kd树最近邻_stepr88_kdtree_K._kd树k近邻_源码.rar

    3. **删除**:kd树的删除操作相对复杂,因为可能需要重新平衡树结构,通常在实际应用中不常用。 4. **分割**:在构建kd树时,选择最优分割维度和位置以最大化子区域间的差异性,这有助于提高搜索效率。 kd树在许多...

    23-Tree:2-3棵树实施为向左倾斜的红黑树

    2-3树是平衡搜索树的一种形式,类似于二叉树,其中某些节点具有2个密钥和3个子代,而不是仅1个密钥和2个子代。 为了实现,我们不是每个节点都有可变数量的键,而是创建一个红黑树:一个二进制树,其中的节点可以被...

    B-树和AVL树源码

    在提供的文件列表中,"SplayTree"可能是指伸展树(Splay Tree),这是一种自调整的二叉搜索树,每次访问节点时都会将其移动到根位置,以优化后续访问。这种数据结构在访问模式具有局部性时表现良好,但并不保证总体...

    some-of-the-binary-tree-algorithm..zip_The Tree

    【描述】提到了其中包含的“超级经典算法”,暗示了我们将探讨的算法包括但不限于二叉查找树(Binary Search Tree, BST)、AVL树、红黑树(Red-Black Tree)、B树、Trie树以及平衡二叉搜索树等。 1. **二叉查找树...

    Two-fork-tree-basic-operation.zip_operation

    对于有序二叉树(如二叉搜索树),从根节点开始,如果目标值小于当前节点,则在左子树中继续搜索;反之,在右子树中搜索。 4. **删除节点**: 删除节点是最复杂的操作之一,因为它可能涉及重新排列子树。根据要...

    Python库 | red-black-tree-mod-1.11.tar.gz

    3. **时间复杂度**:由于红黑树的自平衡性质,插入、删除和查找操作的时间复杂度都是O(log n),其中n是树中的节点数。这使得红黑树在处理大量数据时表现优秀。 4. **应用**:红黑树在多种场景下被广泛使用,如C++ ...

    前端开源库-node-interval-tree

    节点间隔树基于二叉搜索树(Binary Search Tree, BST)的概念,但每个节点不仅包含一个值,还包含一个区间。这种数据结构的设计使得在O(log n)的时间复杂度内完成区间查询、插入和删除操作成为可能。区间查询能够...

    binary-tree-master (3).zip

    在二叉树的实现中,常见的数据结构包括二叉搜索树(BST)、完全二叉树、满二叉树、平衡二叉树(如AVL树和红黑树)等。每个都有其特定的性质和操作,如插入、删除、查找等。C语言实现这些操作时,需要考虑指针的使用...

    binary-tree-traversal-binary-tree.zip_tree

    查找操作在二叉搜索树中尤为高效,因为它满足左子树的所有节点值小于根节点,右子树的节点值大于根节点,这使得查找可以在对数时间内完成。插入和删除操作则需要维护树的平衡,以防止退化成链表,降低效率。常见的...

    2_3_tree.rar_23tree_23树实现_2_3_tree

    2-3树在实际应用中主要用于数据库索引、文件系统等场景,它的优点在于插入和删除操作通常比二叉搜索树更快,因为它始终保持平衡。然而,与红黑树、AVL树等其他自平衡树相比,2-3树在实际编程中可能不太常见,因为...

    B.rar_B-树索引_B树_b tree_b tree java_java B-Tree

    1. **B-树结构**:B-树是一种自平衡的多路搜索树,每个节点可以有多个子节点,这些子节点通常称为分支或指针。B-树的每个节点包含一个键值集合和对应的子树指针集合。 2. **度**:B-树的度指的是每个节点最多能有的...

    平衡搜索树

    平衡搜索树是一种特殊的二叉搜索树,其设计目标是为了在最坏的情况下也能保持较高的搜索效率,不至于因为树的不平衡而导致性能显著下降。在平衡搜索树的诸多变种中,红黑树是一种广泛使用的数据结构,它通过在节点中...

Global site tag (gtag.js) - Google Analytics