`
marcoSpring
  • 浏览: 33150 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 二叉搜索树(删除)

 
阅读更多

  二叉树的节点删除要分成三类:删除没有子节点的节点、删除只有一个子节点的节点、删除有两个子节点的节点。第一种和第二种很简单,第三种比较复杂。首先,先从第一种开始
在开始之前先要找到要删除的子节点,这就用到了查找
TreeNode current = root;
		TreeNode parent = root;
		boolean isLeftNode = true;
		while (current.keyValue != Key) {
			parent = current;
			if (Key < current.keyValue) {
				isLeftNode = true;
				current = current.leftNode;
			} else {
				isLeftNode = false;
				current = current.rightNode;
			}
		}
		if (current == null) {
			System.out.println("没有找到要删除的节点!");
			return false;
		}

删除没有子节点的节点: 删除没有子节点的节点只需要将被删除节点的父节点指向空即可。
看图:

图中显示要删除61这个节点,再看代码:
if (current.leftNode == null && current.rightNode == null) {  //要删除的节点没有子节点
			if (current == root) { // 根节点就删除整棵树
				root = null;
			} else if (isLeftNode) { // 如果是左节点,做节点指向空
				parent.leftNode = null;
			} else { // 如果是右节点,右节点指向空
				parent.rightNode = null;
			}
		}

删除有一个子节点的节点:删除有一个子节点的节点,只需要将被删除节点的父节点指向删除节点的子节点即可
看图:

要删除84这个节点。代码:
if (current.leftNode == null) {                         //要删除的节点只有右节点
			if (current == root) { 
				root = current.rightNode;
			} else if (isLeftNode) {
				parent.leftNode = current.rightNode;
			} else {
				parent.rightNode = current.rightNode;
			}
		} else if (current.rightNode == null) {                         //要删除的节点只有左节点
			if (current == root) { 
				root = current.leftNode;
			} else if (isLeftNode) {
				parent.leftNode = current.leftNode;
			} else {
				parent.rightNode = current.leftNode;
			}
		} 

删除有两个子节点的节点:删除有两个子节点的节点,到底谁来替代被删除的节点的位置呢?是左节点,还是右节点,代替以后这个子节点的子节点应该怎么安排?一系列的问题都出来了。。。简便的方法就是要找一个节点代替这个被删除的节点,这就要从二叉搜索树的定义来看。因为二叉搜索树是有序的,我们要找的节点在这棵树上,而且这个节点要比被删除的左节点大,比右节点小。先看看这个以被删除节点的右节点为根的子树的所有节点的值都要比被删除节点大,这是二叉搜索树定义的,但是要在这个集合中找到最小的一个,来代替被删除的节点,那就要在这棵子树上一直往左找。这个节点比被删除的节点的右节点小,且比左节点大,那这个节点就叫做被删除节点的后继节点,用这个节点来代替被删除节点。
来看一下代码:
private TreeNode findSuccessor(TreeNode delNode){
		TreeNode parent = delNode;
		TreeNode successor = delNode;
		TreeNode current = delNode.rightNode;
		while(current != null){
			parent = successor;
			successor = current;
			current = current.leftNode;
		}
		//这段代码的作用是当后继节点不是被删除节点的右节点并且后继结点有右节点的情况下的时候做的操作
		if(successor != delNode.rightNode){
			parent.leftNode = successor.rightNode;
			successor.rightNode = delNode.rightNode;
		}
		return successor;
	}

找到了后继节点剩下的事情就简单了只需要将被删除节点替换为后继节点就可以了,这里的过程要注意各种指针的指向。
代码:
TreeNode successor = findSuccessor(current);
			if(current == root){
				root = successor;
			}else if(isLeftNode){
				parent.leftNode = successor;
			}else{
				parent.rightNode = successor;
			}
			successor.leftNode = current.leftNode;

--------------------------------------------------------------------------------------------------------------------------------------
下面给出整个树的代码:
package test;

/**
 * @author 作者 MarcoSpring:
 * @version 创建时间:2012-8-3 上午10:14:51 二叉搜索树
 */
public class Tree {
	public TreeNode root;// 根节点

	// 查找节点
	public TreeNode search(int Key) {
		TreeNode node = root;
		// 首先定义一个节点让其指向根,在下面的循环中
		// 只要节点值不等于要查找的节点值就进入循环如果没有找到则返回null
		while (node.keyValue != Key) {
			if (Key < node.keyValue) { // 如果要查找的值小于节点值则指向左节点
				node = node.leftNode;
			} else { // 否则指向右节点
				node = node.rightNode;
			}
			if (node == null) { // 如果节点为空了则返回null
				return null;
			}
		}
		return node;
	}

	// 添加节点
	public void insert(int Key) {
		TreeNode node = new TreeNode(Key);
		// 添加节点之前首先要找到要添加的位置,这样就要记住要添加节点的父节点
		// 让父节点的左右指向要添加的节点
		if (root == null) { // 如果根结点为空,则根节点指向新节点
			root = node;
		} else {
			TreeNode currentNode = root;// 定义当前节点并指向根节点
			TreeNode parentNode;
			while (true) { // 寻找节点添加的位置
				parentNode = currentNode;
				if (Key < currentNode.keyValue) {
					currentNode = currentNode.leftNode;
					if (currentNode == null) { // 当找到空节点的时候,父节点的左节点指向新节点
						parentNode.leftNode = node;
						return;
					}
				} else {
					currentNode = currentNode.rightNode;
					if (currentNode == null) { // 当找到空节点的时候,父节点的右节点指向新节点
						parentNode.rightNode = node;
						return;
					}
				}
			}
		}
	}

	// 遍历树
	public void display(TreeNode node) {
		if (node != null) {
			display(node.leftNode);
			System.out.println(node.keyValue + ",");
			display(node.rightNode);
		}
	}

	// 最大值
	public int max() {
		TreeNode node = root;
		TreeNode parent = null;
		while (node != null) {
			parent = node;
			node = node.rightNode;
		}
		return parent.keyValue;
	}

	// 最小值
	public int min() {
		TreeNode node = root;
		TreeNode parent = null;
		while (node != null) {
			parent = node;
			node = node.leftNode;
		}
		return parent.keyValue;
	}

	// 删除节点分三种方式删除节点
	// 1、删除没有子节点的节点,直接让该节点的父节点的左节点或右节点指向空
	// 2、删除有一个子节点的节点,直接让该节点的父节点指向被删除节点的剩余节点
	// 3、删除有三个节点的子节点,找到要删除节点的后继节点, 用该节点替代删除的节点
	public boolean delete(int Key) {
		// 首先查找节点,并记录该节点的父节点引用
		TreeNode current = root;
		TreeNode parent = root;
		boolean isLeftNode = true;
		while (current.keyValue != Key) {
			parent = current;
			if (Key < current.keyValue) {
				isLeftNode = true;
				current = current.leftNode;
			} else {
				isLeftNode = false;
				current = current.rightNode;
			}
		}
		if (current == null) {
			System.out.println("没有找到要删除的节点!");
			return false;
		}
		// 下面分三种情况删除节点
		if (current.leftNode == null && current.rightNode == null) {  //要删除的节点没有子节点
			if (current == root) { // 根节点就删除整棵树
				root = null;
			} else if (isLeftNode) { // 如果是左节点,做节点指向空
				parent.leftNode = null;
			} else { // 如果是右节点,右节点指向空
				parent.rightNode = null;
			}
		} else if (current.leftNode == null) {                         //要删除的节点只有右节点
			if (current == root) { 
				root = current.rightNode;
			} else if (isLeftNode) {
				parent.leftNode = current.rightNode;
			} else {
				parent.rightNode = current.rightNode;
			}
		} else if (current.rightNode == null) {                         //要删除的节点只有左节点
			if (current == root) { 
				root = current.leftNode;
			} else if (isLeftNode) {
				parent.leftNode = current.leftNode;
			} else {
				parent.rightNode = current.leftNode;
			}
		} else {                                                         //要删除的节点有两个节点
			TreeNode successor = findSuccessor(current);
			if(current == root){
				root = successor;
			}else if(isLeftNode){
				parent.leftNode = successor;
			}else{
				parent.rightNode = successor;
			}
			successor.leftNode = current.leftNode;
		}
		return true;
	}
	
	private TreeNode findSuccessor(TreeNode delNode){
		TreeNode parent = delNode;
		TreeNode successor = delNode;
		TreeNode current = delNode.rightNode;
		while(current != null){
			parent = successor;
			successor = current;
			current = current.leftNode;
		}
		
		if(successor != delNode.rightNode){
			parent.leftNode = successor.rightNode;
			successor.rightNode = delNode.rightNode;
		}
		return successor;
	}
}
  • 大小: 90.4 KB
  • 大小: 80.8 KB
分享到:
评论
2 楼 夏广元 2013-09-20  
删除节点
while (current.keyValue != Key) { 
98.            parent = current; 
99.            if (Key < current.keyValue) { 
100.                isLeftNode = true; 
101.                current = current.leftNode; 
102.            } else { 
103.                isLeftNode = false; 
104.                current = current.rightNode; 
105.            } 
106.        } 
没有考虑到current为null的情况
while(current!= null){
.....
}
1 楼 cuisuqiang 2012-08-07  
不错不错,坚决学习,坚决的!

相关推荐

    Java实现二叉排序树

    二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键(key)、一个关联的值、一个指向左子节点的指针和一个指向右子节点的指针。在二叉排序树中,对于...

    二叉搜索树的源码,加上注释和自己理解

    `BST.java`很可能是二叉搜索树的实现,`TreeDoc.java`可能包含了关于数据结构或树操作的文档,而`BSTMain.java`应该是主程序,用于测试和展示二叉搜索树的功能。 在`BST.java`中,二叉搜索树的节点可能包含以下属性...

    二叉搜索树

    这种特性使得二叉搜索树在进行查找、插入和删除操作时具有较高的效率。 在JAVA中,构建二叉搜索树通常需要定义一个Node类来表示树的节点,节点通常包含一个键值(key)、一个指向左子节点的引用和一个指向右子节点...

    二叉搜索树 转为 双向链表,

    这种特性使得二叉搜索树在搜索、插入和删除操作中具有较高的效率。而将一个二叉搜索树转换为双向链表,可以进一步优化某些操作,如顺序遍历,因为链表提供了连续的访问方式。 双向链表(Doubly Linked List)是一种...

    Java创建二叉搜索树,实现搜索,插入,删除的操作实例

    Java 创建二叉搜索树、实现搜索、插入、删除的操作实例 Java 创建二叉搜索树是指通过 Java 语言实现一个二叉搜索树数据结构,该树具有查找、插入、删除等操作的功能。二叉搜索树是一种特殊的二叉树,每个节点的值...

    数据结构 二叉排序树 java图形界面实现

    二叉排序树(Binary Sort Tree,也称为二叉搜索树),是数据结构中的一种特殊类型树,它具有以下特性:对于任意一个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。...

    使用Java实现二叉搜索树

    这段代码展示了构建一个基本的二叉搜索树(Binary Search Tree, BST)的实现。二叉搜索树是一种特殊的二叉树,其中每个节点的值大于其左子树中所有节点的值,并且小于其右子树中所有节点的值。这种数据结构在查找、...

    红黑树、二叉平衡树、二叉排序树的java实现

    其次,二叉平衡树(AVL树)是最早被提出的自平衡二叉搜索树,由G. M. Adelson-Velsky和E. M. Landis于1962年提出。AVL树要求每个节点的两个子树的高度差不超过1,以确保树的高度保持在log2(n+1)的范围内。为了维持这...

    java-leetcode题解之第98题验证二叉搜索树.zip

    这个“java-leetcode题解之第98题验证二叉搜索树.zip”压缩包文件显然是针对LeetCode上的第98题提供的Java解决方案。这道题目涉及的核心知识点是二叉搜索树(Binary Search Tree, BST)和树的遍历。 **二叉搜索树**...

    java实现 二叉搜索树功能

    Java 实现二叉搜索树功能 二叉搜索树是一种特殊的二叉树,它的每个节点都含有一个...二叉搜索树的优点是可以快速地查找、插入和删除元素,但是它的缺点是需要维护树的平衡,以保证查找、插入和删除操作的效率。

    tree-java.rar_tree_二叉搜索树

    - `BinarySearchTree.java`: 实现二叉搜索树的主要逻辑,包括插入、查找和删除方法。 ```java public class BinarySearchTree { private Node root; public void insert(int key, int value) { // 插入逻辑,...

    二叉查找树java

    以上就是关于二叉查找树在Java中的基本实现,包括插入、删除、遍历和查询等操作。通过这些操作,我们可以高效地管理一组有序数据,并进行各种数据操作。二叉查找树在实际应用中广泛用于数据库索引、文件系统以及各种...

    二叉排序树查找算法

    二叉排序树(Binary Search Tree,BST),也称为二叉查找树或有序二叉树,是一种自平衡的二叉树数据结构,它在处理搜索、插入和删除操作时具有较高的效率。二叉排序树的主要特点是:对于任意节点,其左子树中的所有...

    二叉搜索树程序

    在压缩包`BinarySearchTree`中,可能包含了用各种编程语言(如C++、Java、Python等)实现的二叉搜索树代码。这些代码可能包括了上述的基本操作函数,以及可能的优化或扩展功能,如遍历(前序、中序、后序)和序列化/...

    Java实现的二叉搜索树和平衡二叉树的代码示例

    这种特性使得二叉搜索树在查找、插入和删除操作上具有高效的性能。 平衡二叉树(Balanced Binary Tree)是二叉搜索树的一种优化,它的左右两个子树的高度差不超过1,并且左右两个子树都是一棵平衡二叉树。常见的...

    二叉搜索树代码.zip

    常见的编程语言如C++、Java、Python都有库支持二叉搜索树的实现。 总的来说,二叉搜索树是一种高效的数据结构,能够快速地执行查找、插入和删除操作,适用于需要频繁进行这些操作的场景。理解并熟练掌握二叉搜索树...

    Java基于二叉查找树实现排序功能示例

    Java二叉查找树有很多的应用场景,例如排序、查找、插入和删除等。在实际应用中,我们可以使用二叉查找树来实现高效的排序和查找操作。同时,二叉查找树也可以用于解决一些复杂的算法问题,例如拓扑排序和最短路径等...

    简单二叉查找树的java实现

    二叉查找树的实现。包括树的平衡以及树节点的删除。以及树的广度优先遍历,深度优先遍历。

    数据结构二叉平衡树课程设计

    二叉平衡树是一种特殊类型的二叉树,它在保持二叉搜索树特性的同时,通过特定的结构调整策略确保了树的高度平衡。这样的平衡状态使得在树中进行查找、插入和删除等操作的时间复杂度都能保持在对数级别,极大地提高了...

    二叉搜索树练习 HDU3791

    总结来说,"二叉搜索树练习 HDU3791"是一道关于二叉搜索树操作的编程题,可能需要实现插入、删除、查找等基本操作,并通过分析`Main.java`源码来理解和解决问题。同时,可能需要借助各种工具进行调试和测试,以确保...

Global site tag (gtag.js) - Google Analytics