- 浏览: 202640 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
NIghtmare28:
太好用了, 谢谢
Create Local Cloudera Parcels Repo to Save Your ASS -
oyxccyj:
你好,请问下你如上的问题解决了吗?我现在也遇到同样的问题,网上 ...
Homework - HBase Shell, Java Client and MapReduce Job -
20131007:
用java描述算法?
基础数据结构和算法二:Selection sort -
ender35:
第二种实现仅能用于数组排序
计数排序(Counting Sort) -
fy616508150:
我想知道有括号参加运算怎么办
算24算法实现
删除节点是二叉搜索树操作中最复杂的,但对有些应用又非常重要,有必要好好研究一下。
一个取巧的办法:在树节点中加入一个boolean字段,比如isDeleted。需要删除一个节点时就把这个字段置为true,其他操作比如find()在查找之前先判断这个节点是否已经标记为删除了,这样删除的节点将不会改变树的结构,当然这样做还会继续保留这种已经删除的节点。对某些应用场景,这种做法是有优势的,比如已经离职的员工档案要保留在员工记录中。
下面来实现这个删除节点的算法。首先列出树节点的数据结构:
/** * @author Sun Kui */ public class Node { // node key public int iData; // node value public double dData; public Node leftChild; public Node rightChild; public Node() { this(0, 0.0); } public Node(int id, double dd) { this.iData = id; this.dData = dd; } public void displayNode() { System.out.print('{'); System.out.print(iData); System.out.print(", "); System.out.print(dData); System.out.print("} "); } @Override public String toString() { return iData + "=>" + dData; } }
删除节点首先从查找要删除的节点入手:
Node cur = root, parent = root; boolean isLeftChild = true; while (cur.iData != key) { parent = cur; if (key < cur.iData) { isLeftChild = true; cur = cur.leftChild; } else { isLeftChild = false; cur = cur.rightChild; } // no node to delete if (cur == null) { return false; } }
找到节点后,有三中可能的情况需要考虑:
1.该节点是叶子节点
2.该节点有一个子节点
3.该节点有两个子节点
情况1:
要删除叶子节点,只需要改变该节点的父节点对应子字段的值,代码如下:
if (cur.leftChild == null && cur.rightChild == null) { if (cur == root) { // remove root node root = null; } else if (isLeftChild) { cur.leftChild = null; } else { cur.rightChild = null; } }
情况2:
要删除的节点有一个子节点(左子节点或者右子节点),要从二叉搜索树中”剪断“这个节点,并把它的子节点连接到它的父节点上,这个过程要求改变父节点的适当引用,指向要删除的子节点。一共有4种情况:要删除的子节点可能有左子节点或者右子节点,并且每种情况中的要删除节点也可能是自己父节点的左子节点或者右子节点。另外还有一种特殊情况:被删除的节点可能是根节点,它没有父节点,只是被合适的子树代替。代码如下:
else if (cur.leftChild == null) { // left child node is null if (cur == root) { root = cur.rightChild; } else if (isLeftChild) { parent.leftChild = cur.rightChild; } else { parent.rightChild = cur.rightChild; } } else if (cur.rightChild == null) { // right child node is null if (cur == root) { root = cur.leftChild; } else if (isLeftChild) { parent.leftChild = cur.leftChild; } else { parent.rightChild = cur.leftChild; } }
情况3:
要删除有两个子节点的节点,要用其中序后继节点来代替该节点。找后继节点的算法如下:首先找到初始节点的右子节点,它的关键字值一定比初始节点大。然后转到初始节点的右子节点的左子节点(如果有的话),然后继续到该左子节点的左子节点,顺着左子节点的路径一直向下找。这个路径的最后一个左子节点就是初始节点的后继。代码如下:
/** * Returns node with next highest value after node to delete goes to right * child, then right child's left descendants * * This method assume that the node to delete has right child, for it's has * been checked in previous in delete() method. * * @param node * to delete */ private Node getSuccessor(Node delNode) { Node successorParent = delNode; Node successor = delNode; // go to right child of node to delete Node current = delNode.rightChild; // loop until no more left children while (current != null) { successorParent = successor; successor = current; // go to left child current = current.leftChild; } // if successor is not right child, make connections,prepared for deletion if (successor != delNode.rightChild) { successorParent.leftChild = successor.rightChild; successor.rightChild = delNode.rightChild; } return successor; }
找到后继节点以后,后继节点可能与要删除的节点有两种位置关系:后继节点可能是要删除节点的右子节点,也可能是其左子孙节点。如果是右子节点情况就简单了一些,只需要把以后继节点为根的子数移到要删除节点的位置。否则要进行更复杂的操作,情形3的完整代码如下:
else { // two children, so replace with in-order successor // get successor Node successor = getSuccessor(cur); // connect parent of current to successor instead if (cur == root) { root = successor; } else if (isLeftChild) { parent.leftChild = successor; } else { parent.rightChild = successor; } // connect successor to current's left child successor.leftChild = cur.leftChild; } return true;
请注意,getSuccessor()的代码中,已经完整了删除的部分操作。
最后贴出二叉搜索树删除节点算法的完整代码:
public boolean delete(int key) { Node cur = root, parent = root; boolean isLeftChild = true; while (cur.iData != key) { parent = cur; if (key < cur.iData) { isLeftChild = true; cur = cur.leftChild; } else { isLeftChild = false; cur = cur.rightChild; } // no node to delete if (cur == null) { return false; } } if (cur.leftChild == null && cur.rightChild == null) { if (cur == root) { // remove root node root = null; } else if (isLeftChild) { cur.leftChild = null; } else { cur.rightChild = null; } } else if (cur.leftChild == null) { // left child node is null if (cur == root) { root = cur.rightChild; } else if (isLeftChild) { parent.leftChild = cur.rightChild; } else { parent.rightChild = cur.rightChild; } } else if (cur.rightChild == null) { // right child node is null if (cur == root) { root = cur.leftChild; } else if (isLeftChild) { parent.leftChild = cur.leftChild; } else { parent.rightChild = cur.leftChild; } } else { // two children, so replace with in-order successor // get successor Node successor = getSuccessor(cur); // connect parent of current to successor instead if (cur == root) { root = successor; } else if (isLeftChild) { parent.leftChild = successor; } else { parent.rightChild = successor; } // connect successor to current's left child successor.leftChild = cur.leftChild; } return true; }
测试代码如下:
import java.util.Random; /** * @author Sun Kui */ public class Main { public static void main(String... args) { BinarySearchTree theTree = new BinarySearchTree(); if (args.length < 1) { System.out.println("Usage: java Main number"); return; } int count = Integer.parseInt(args[0]); Random rand = new Random(); for (int i = 0; i < count; i++) { theTree.insert(rand.nextInt(count * count), rand.nextDouble() + 1); } theTree.insert(35, 1.8); Node found = theTree.find(35); System.out.println(found); theTree.inOrder(theTree.getRootNode()); } }
end.
发表评论
-
基础数据结构和算法十四:Directed Graphs
2013-12-15 22:40 1806In directed graphs, edges a ... -
基础数据结构和算法十三:Undirected Graphs (2)
2013-12-13 22:51 1063Design pattern for graph p ... -
基础数据结构和算法十三:Undirected Graphs
2013-12-13 20:15 1204A graph is a set of vertices ... -
基础数据结构和算法十二:Hash table
2013-12-02 22:06 1049Search algorithms that use ... -
基础数据结构和算法十一:Red-black binary search tree
2013-12-01 12:12 1516The insertion algorithm fo ... -
基础数据结构和算法十:2-3 search tree
2013-11-30 11:07 1215Binary search tree works w ... -
基础数据结构和算法九:Binary Search Tree
2013-11-28 22:39 1671A binary search tree (BST) ... -
基础数据结构和算法八:Binary search
2013-11-28 21:21 1142Binary search needs an ordere ... -
基础数据结构和算法七:Priority queue & Heap sort
2013-11-27 19:47 2712Some important applications o ... -
基础算法七: Priority queue & Heap sort
2013-11-26 21:46 0Some important applications ... -
基础数据结构和算法六:Quick sort
2013-11-21 19:33 1237Quick sort is probably used m ... -
Inversions of an array
2013-11-20 22:28 0TODO -
基础数据结构和算法五:Merge sort
2013-11-20 21:44 1993One of mergesort’s most at ... -
基础数据结构和算法四:Shell sort
2013-11-20 19:11 1180Shellsort is a simple exte ... -
Comparing two sorting algorithms
2013-11-19 21:16 843Generally we compare algorith ... -
基础数据结构和算法三:Insertion Sort
2013-11-19 21:06 1000As in selection sort, the ite ... -
基础数据结构和算法二:Selection sort
2013-11-19 20:57 1173One of the simplest sortin ... -
基础数据结构和算法一:UnionFind
2013-11-19 20:47 1278The problem that we consid ... -
Three-sum with linear time complexity
2013-09-14 10:08 0TODO package org.george.algor ... -
Blooming Filter in Hadoop
2013-07-27 22:49 0TODO
相关推荐
二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或二叉搜索树,是一种自平衡的二叉树数据结构,它在处理搜索、插入和删除操作时具有较高的效率。二叉排序树的主要特性是:对于任意节点,其左子树中的所有...
在二叉搜索树中,对于任何一个节点,其左子树中的所有节点的键都小于该节点的键,而右子树中的所有节点的键都大于该节点的键。这种特性使得二叉搜索树在查找、插入和删除操作上具有较高的效率。 `bstree.cpp`和`...
二叉搜索树(Binary Search Tree,BST),是数据结构领域中的一个重要概念,它是一种特殊的二叉树,每个节点的左子树只包含比其小的元素,而右子树则包含大于它的元素。这种特性使得二叉搜索树在查找、插入和删除...
下面是一个简单的二叉搜索树节点模板类的示例: ```cpp template struct TreeNode { T value; TreeNode* left; TreeNode* right; }; ``` 接下来,我们可以实现查找算法。在二叉搜索树中查找一个值,我们从根...
最优二叉搜索树,也称为最优化二叉查找树或者动态二叉搜索树,是计算机科学中的一个重要概念,尤其在算法设计与分析领域占据一席之地。这种数据结构主要用于提高查询效率,在某些特定操作序列下,它能比普通二叉搜索...
【最优二叉搜索树问题】是一种在数据结构和算法领域中的经典问题,主要涉及动态规划的概念。该问题的目标是设计一棵二叉搜索树(BST),使得在给定的元素集合和存取概率分布下,搜索元素时的平均比较次数达到最小。 ...
最优二叉搜索树,也称为最优化二叉查找树或动态二叉查找树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键值和两个子节点,左子节点的键值小于当前节点,右子节点的键值大于当前节点。在最优二叉搜索树中,...
4. **删除算法**:删除二叉搜索树中的某个节点。情况复杂,包括删除叶子节点、只有一个子节点的节点以及有两个子节点的节点。 ```cpp TreeNode* deleteNode(TreeNode* root, int key) { // ... 实现删除逻辑 ... }...
在二叉搜索树中,对于任意节点而言,其左子树中的所有节点的键值都小于该节点的键值,而右子树中的所有节点的键值都大于该节点的键值。这种特性使得二叉搜索树在查找、插入和删除操作上具有较高的效率,尤其是在树...
根据给定文件的信息,我们...通过以上内容的学习,可以进一步加深对指针、动态变量的理解,同时掌握二叉树及其存储结构的特点和应用,特别是二叉搜索树的相关算法。这对于后续学习更复杂的数据结构和算法非常有帮助。
2. **删除操作**:从二叉搜索树中移除指定节点。删除操作相对复杂,因为它涉及三种情况:要删除的节点没有子节点、有一个子节点和有两个子节点。没有子节点的情况直接删除即可;有一个子节点时,用子节点替换要删除...
同时,为了不创建新节点,我们需要直接修改原二叉搜索树节点的prev和next指针。 在实际编程实现时,通常会用到栈或递归的方法。使用栈时,我们可以从根节点开始,将大于当前节点的右子节点压入栈中,然后弹出栈顶...
在二叉搜索树中,对于任意节点,其左子树中的所有节点的键都小于该节点的键,而右子树中的所有节点的键都大于该节点的键。这种特性使得二叉搜索树在插入、删除和查找操作上具有较高的效率。 在提供的源码中,我们...
二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树数据结构,其中每个节点包含一个键值(key),且满足以下条件:对于任意节点而言,其左子树中的所有节点的键值均小于该节点的键值;其右子树中的所有节点的键值...
总之,二叉搜索树是一种重要的数据结构,它提供了快速的查找、插入和删除功能,广泛应用于各种算法和数据管理中。通过分析和理解“二叉搜索树.c”的源代码,我们可以深入学习二叉搜索树的原理和实现细节,这对于学习...
在二叉搜索树中,对于任意节点,其左子树中的所有节点的键都小于该节点的键,而右子树中所有节点的键都大于该节点的键。这种特性使得二叉搜索树在查找、插入和删除操作上具有较高的效率。 在给定的文件列表中,我们...
**最优二叉搜索树**(Optimal Binary Search Tree,简称OBST)是一种特殊的二叉搜索树,其节点按照特定的方式排列,使得在进行搜索操作时所需的平均成本最小。在实际应用中,构建一个最优的二叉搜索树能够有效提高数据...
在二叉搜索树中,对于任何一个节点,其左子树中的所有节点的键都小于该节点的键,而右子树中的所有节点的键都大于该节点的键。这种特性使得二叉搜索树非常适合进行查找、插入和删除等操作。 在提供的压缩包文件中,...
在这个问题中,我们用C#语言实现了动态规划算法来构建最优二叉搜索树。动态规划是一种解决最优化问题的有效方法,它将大问题分解为小问题,然后通过构建子问题的最优解来获得原问题的最优解。 首先,我们需要理解...
这种性质使得在二叉搜索树中查找、插入和删除操作的时间复杂度在平均情况下为O(log n),其中n是树中节点的数量。 在C++中实现二叉搜索树,一般会定义一个二叉树节点类(如代码中的`BinaryTreeNode`),包含数据成员...