Java實現二叉排序樹的插入、查詢、刪除
阿新 • • 發佈:2018-12-29
import java.util.Random; /** * 二叉排序樹(又稱二叉查詢樹) * (1)可以是一顆空樹 * (2)若左子樹不空,則左子樹上所有的結點的值均小於她的根節點的值 * (3)若右子樹不空,則右子樹上所有的結點的值均大於她的根節點的值 * (4)左、右子樹也分別為二叉排序樹 * * * 效能分析: * 查詢效能: * 含有n個結點的二叉排序樹的平均查詢長度和樹的形態有關, * (最壞情況)當先後插入的關鍵字有序時,構成的二叉排序樹蛻變為單枝樹。查詢效能為O(n) * (最好情況)二叉排序樹的形態和折半查詢的判定樹相同,其平均查詢長度和log2(n)成正比 * * * 插入、刪除效能: * 插入、刪除操作間複雜度都O(log(n))級的, * 即經過O(log(n))時間搜尋到了需插入刪除節點位置和刪除節點的位置 * 經O(1)級的時間直接插入和刪除 * 與順序表相比,比序順序表插入刪除O(n)(查詢時間O(log(n))移動節點時間O(n))要快 * 與無序順序表插入時間O(1),刪除時間O(n)相比,因為是有序的,所查詢速度要快很多 * * * * 作者:小菜鳥 * 建立時間:2014-08-17 * */ public class BinarySortTree { private Node root = null; /**查詢二叉排序樹中是否有key值*/ public boolean searchBST(int key){ Node current = root; while(current != null){ if(key == current.getValue()) return true; else if(key < current.getValue()) current = current.getLeft(); else current = current.getRight(); } return false; } /**向二叉排序樹中插入結點*/ public void insertBST(int key){ Node p = root; /**記錄查詢結點的前一個結點*/ Node prev = null; /**一直查詢下去,直到到達滿足條件的結點位置*/ while(p != null){ prev = p; if(key < p.getValue()) p = p.getLeft(); else if(key > p.getValue()) p = p.getRight(); else return; } /**prve是要安放結點的父節點,根據結點值得大小,放在相應的位置*/ if(root == null) root = new Node(key); else if(key < prev.getValue()) prev.setLeft(new Node(key)); else prev.setRight(new Node(key)); } /** * 刪除二叉排序樹中的結點 * 分為三種情況:(刪除結點為*p ,其父結點為*f) * (1)要刪除的*p結點是葉子結點,只需要修改它的雙親結點的指標為空 * (2)若*p只有左子樹或者只有右子樹,直接讓左子樹/右子樹代替*p * (3)若*p既有左子樹,又有右子樹 * 用p左子樹中最大的那個值(即最右端S)代替P,刪除s,重接其左子樹 * */ public void deleteBST(int key){ deleteBST(root, key); } private boolean deleteBST(Node node, int key) { if(node == null) return false; else{ if(key == node.getValue()){ return delete(node); } else if(key < node.getValue()){ return deleteBST(node.getLeft(), key); } else{ return deleteBST(node.getRight(), key); } } } private boolean delete(Node node) { Node temp = null; /**右子樹空,只需要重接它的左子樹 * 如果是葉子結點,在這裡也把葉子結點刪除了 * */ if(node.getRight() == null){ temp = node; node = node.getLeft(); } /**左子樹空, 重接它的右子樹*/ else if(node.getLeft() == null){ temp = node; node = node.getRight(); } /**左右子樹均不為空*/ else{ temp = node; Node s = node; /**轉向左子樹,然後向右走到“盡頭”*/ s = s.getLeft(); while(s.getRight() != null){ temp = s; s = s.getRight(); } node.setValue(s.getValue()); if(temp != node){ temp.setRight(s.getLeft()); } else{ temp.setLeft(s.getLeft()); } } return true; } /**中序非遞迴遍歷二叉樹 * 獲得有序序列 * */ public void nrInOrderTraverse(){ Stack<Node> stack = new Stack<Node>(); Node node = root; while(node != null || !stack.isEmpty()){ while(node != null){ stack.push(node); node = node.getLeft(); } node = stack.pop(); System.out.println(node.getValue()); node = node.getRight(); } } public static void main(String[] args){ BinarySortTree bst = new BinarySortTree(); /**構建的二叉樹沒有相同元素*/ int[] num = {4,7,2,1,10,6,9,3,8,11,2, 0, -2}; for(int i = 0; i < num.length; i++){ bst.insertBST(num[i]); } bst.nrInOrderTraverse(); System.out.println(bst.searchBST(10)); bst.deleteBST(2); bst.nrInOrderTraverse(); } /**二叉樹的結點定義*/ public class Node{ private int value; private Node left; private Node right; public Node(){ } public Node(Node left, Node right, int value){ this.left = left; this.right = right; this.value = value; } public Node(int value){ this(null, null, value); } public Node getLeft(){ return this.left; } public void setLeft(Node left){ this.left = left; } public Node getRight(){ return this.right; } public void setRight(Node right){ this.right = right; } public int getValue(){ return this.value; } public void setValue(int value){ this.value = value; } } }