数据结构:二叉搜索树(BST)的基本操作
概述
? 學習過數據結構的童鞋都應該知道,對樹的操作是一些最基本的技能(本文是對后面要寫B樹、B-樹、B+樹的一個前導,已經熟悉的朋友可以跳過了)。而在樹結構中,二叉樹又是最基礎的。雖然這些知識是比較基礎的,不過對于BST的操作中,刪除是一個相對比較麻煩的。這對于新手來說可能不太好理解,下面就以BST中節點的刪除為主,其他操作為輔的策略來編寫本篇文章。希望對你能有所幫助。
?
版權說明
著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
作者:Q-WHai
發表日期: 2015年12月21日
鏈接:https://qwhai.blog.csdn.net/article/details/50366993
來源:CSDN
更多內容:分類 >> 算法與數學
?
基本操作:
1.插入
?
public void insert(int _value) {Node node = root;boolean inserted = false;while(!inserted) {if (_value == node.getValue()) {inserted = true;} else if (_value < node.getValue()) {Node leftNode = node.getLeft();if (leftNode == null) {leftNode = new Node(_value);node.setLeft(leftNode);inserted = true;} else {node = leftNode;}} else {Node rightNode = node.getRight();if (rightNode == null) {rightNode = new Node(_value);node.setRight(rightNode);inserted = true;} else {node = rightNode;}}}}?
2.查找
? 這里就拿找到一個待刪除節點為例作說明。
?
private Node[] searchRemoveNode(int _value) {Node parentNode = null;Node removeNode = root;while(removeNode != null) {if (removeNode.getValue() == _value) {break;}if (removeNode.getValue() < _value) {parentNode = removeNode;removeNode = removeNode.getRight();}if (removeNode.getValue() > _value) {parentNode = removeNode;removeNode = removeNode.getLeft();}}return new Node[]{parentNode, removeNode};}?
3.刪除
? 嗯,重點來了。
? 關于二叉搜索樹的刪除是相對比較麻煩的。這是為什么呢?我們知道二叉搜索可以快速查找某一個元素是否存在的原因,是BST遵循了一些規則。而我們麻煩的原因也正因為這個規則。
? 或許你會說,刪除有什么難的。直接記錄一下待刪除節點的左、右孩子節點,再遍歷孩子節點并按之前的方式插入到BST中不就是可以了么?有什么難的?
? 這是一個思路,但是不是太好,因為使用它我們總是會有一種提心吊膽的感覺。為什么?我們現在說明一種情況。比方說,我有一棵BST。它的待刪除節點是10000,左右孩子節點都有9999個節點。那么是不是就是說我們還要再把這9999 * 2個節點再插入到BST中呢?而且插入過程中還有對樹的遍歷。
? 說明上面那么太過生硬的方法之后,現在我就來說一個軟一點的方法。我們先來看下面的三張圖:
圖-1 刪除一個無子節點的節點
圖-2 刪除只有一個子節點的節點
圖-3 刪除有兩個子節點的節點
?
? 從上面的三張圖我們就可以看出,要刪除BST中的一個節點是要分情況討論的。在第一種情況中,沒什么好說的,就是直接刪除就OK。代碼如下:
?
private void removeNodeNoChild(Node parentNode, Node removeNode) {if (parentNode.getValue() == removeNode.getValue()) {return;} else if (parentNode.getValue() < removeNode.getValue()) {parentNode.setRight(null);} else {parentNode.setLeft(null);}}? 在第二種方法中,我要刪除節點80。不過這個時候不能直接刪除,因為待刪除節點有一個子節點。我們把這個子節點掛到節點80的話父節點上就可以了。代碼如下:
?
private void removeNodeOneChild(Node parentNode, Node removeNode) {if (parentNode.getValue() == removeNode.getValue()) {return;}if (removeNode.getValue() < parentNode.getValue()) {// 父節點的左孩子parentNode.setLeft(removeNode.getLeft() == null ? removeNode.getRight() : removeNode.getLeft());} else {// 父節點的右孩子parentNode.setRight(removeNode.getLeft() == null ? removeNode.getRight() : removeNode.getLeft());}}? 第三種情況就復雜一些。因為我們既不能直接刪除,也不能把節點30的子節點掛到節點30的父節點20上面(因為每個節點的右孩子只能有一個,而節點30有兩個孩子)。
?
? 我們的做法是找到待刪除節點(節點30)左孩子中最大的節點,這里我們打到了節點27。再把節點27來替換掉要刪除的節點30。這樣既快捷高效又保證不破壞BST的規則結構。代碼如下:
?
private void removeNodeTwoChild(Node parentNode, Node removeNode) {if (parentNode.getValue() == removeNode.getValue()) {return;}Node maxValueNode = maxValueNode(removeNode.getLeft());if (removeNode.getValue() < parentNode.getValue()) {// 父節點的左孩子parentNode.setLeft(maxValueNode);} else {// 父節點的右孩子parentNode.setRight(maxValueNode);}maxValueNode.setLeft(removeNode.getLeft());maxValueNode.setRight(removeNode.getRight());}?
Demo源碼下載:
https://github.com/qwhai/simple-tree
?
征集
如果你也需要使用ProcessOn這款在線繪圖工具,可以使用如下邀請鏈接進行注冊:
https://www.processon.com/i/56205c2ee4b0f6ed10838a6d
總結
以上是生活随笔為你收集整理的数据结构:二叉搜索树(BST)的基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式——Builder模式
- 下一篇: 算法:关于生成抽样随机数的这些算法