1. 程式人生 > >二叉排序樹(二叉查詢樹)BST構造,節點插入,節點查詢,節點刪除(java)

二叉排序樹(二叉查詢樹)BST構造,節點插入,節點查詢,節點刪除(java)

  • 二叉排序樹(BST)的構造,節點插入,節點查詢,節點刪除(java)
    高度最小BST(同樣資料,順序可能不一樣)
package ccnu.offer.tree;

import java.util.ArrayList;
import java.util.Arrays;

// 二叉排序樹(二叉查詢樹)BST
// 對於給定陣列(資料完全一樣,並且資料順序一定)構造二叉排序樹一定,但是資料一樣,順序不一樣,那麼排序樹就不一樣
// 構造高度最小的二叉排序樹,那麼就需要有如下要求:儘可能將陣列中還未插入的資料的中位數作為根節點
public class Demo04 {
    public static
void main(String[] args) { int[] datas = new int[]{53, 17, 78, 9, 45, 65, 94, 23, 81, 88}; // page149:4-22 Node root = null; root = removeBSTNode(createBST(root, datas), 78); inOrder(root); } // 二叉排序樹的構造:就是不斷的插入新節點 public static Node createBST(Node root, int
[] datas){ root = null; int index = 0; while(index < datas.length){ root = insertBST(root, datas[index]); index++; // 插入下一個節點 } return root; } // 二叉排序樹的插入 public static Node insertBST(Node root, int data){ // 插入的新節點一定為葉子 if
(root == null){ // 以root為根節點的樹為空樹 root = new Node(data); // 左右子樹均為空 } /*else if(data == root.data){ // 已存在此值的節點 return root; }*/ else if(data <= root.data){ // 插入到root的左子樹上 root.lchild = insertBST(root.lchild, data); }else{ // 插入到root的右子樹上 root.rchild = insertBST(root.rchild, data); } return root; } // 二叉查詢樹中查詢指定關鍵字值節點 public static Node searchBST(Node root, int data){ Node p = null; // 此處可得到所要找到節點的父節點 while(root != null && root.data != data){ // 當前樹非空並且所找節點不是當前樹的根節點 p = root; if(data < root.data){ root = root.lchild; }else{ root = root.rchild; } } /*if(root == null){ p = null; }*/ // return root; return p; // 返回找到節點的父節點,當p為null,則說明找到的節點為整棵樹的根節點 } // 得到指定樹root中父節點p的關鍵字值為data的孩子節點 public static Node getChild(Node root, Node p, int data){ if(p == null){ // 父節點為空,則找到的關鍵字值為data的節點為整棵樹的根節點root return root; } if(p.lchild == null && p.rchild == null){ // 如果父節點為葉子節點,那麼不存在指定data節點 return null; } if(p.lchild != null && p.lchild.data == data){ return p.lchild; }else{ return p.rchild; } } public static Node searchBST1(Node root, int data){ if(root == null){ return null; }else if(root.data == data){ return root; }else if(data < root.data){ root = searchBST1(root.lchild, data); }else{ root = searchBST1(root.rchild, data); } return root; } // 刪除以root作為根節點的樹中的關鍵字值為data的節點(第一次出現) public static Node removeBSTNode(Node root, int data) { if (root == null) { return null; } Node p = searchBST(root, data); // 找到節點的父節點 Node node = null; // 找到的節點 node = getChild(root, p, data); if (node == null) { // 不存在指定刪除的節點 return root; // 返回原樹根節點 } if (node.lchild == null && node.rchild == null) { // 要刪除的節點為葉子結點,就直接從其父節點上刪除 if (node == root) { // 找到的節點為根節點 等價於p為null root = null; return root; } // 父節點不為空 if (p.lchild != null && p.lchild.data == node.data) { // 如果有左子樹並且左子樹根節點為找到的節點 p.lchild = null; // 直接將這個葉子節點從樹中刪除 } else { p.rchild = null; } node = null; // 刪除節點 } else if (node.lchild != null && node.rchild == null) { // 只有左子樹 if (node == root) { // 找到節點為根節點 root = null; return node.lchild; } if (p.lchild != null && p.lchild.data == node.data) { // 找到節點為父節點的左孩子節點 p.lchild = node.lchild; } else { p.rchild = node.lchild; } } else if (node.lchild == null && node.rchild != null) { // 只有右子樹 if (node == root) { // 找到節點為根節點 root = null; return node.rchild; } if (p.lchild != null && p.lchild.data == node.data) { p.lchild = node.rchild; } else { p.rchild = node.rchild; } } else { // 待刪除節點左右子樹均有,則應該將待刪除節點的直接前驅(中序遍歷,比刪除節點關鍵字值不大於節點的最大節點)結點替代,或者 // 將待刪除節點的直接後繼(中序遍歷,比刪除節點關鍵字值不小於節點的最小節點)結點替代,進而將問題轉換為刪除剛才的替代節點 // 此處實現的是用刪除節點的直接後繼結點替代 Node nextNode = node.rchild; // 刪除節點的直接後繼,實際上這個直接後繼節點或者是葉子結點或者是隻有右子樹的節點 while (nextNode.lchild != null) { nextNode = nextNode.lchild; } removeBSTNode(node, nextNode.data); // 在待刪除的節點為根節點的樹中刪除其直接後繼節點nextNode nextNode.lchild = node.lchild; // 將刪除節點的左子樹作為後繼節點的左子樹 nextNode.rchild = node.rchild; // 將刪除節點的右子樹作為後繼節點的右子樹 if (node == root) { // 刪除節點為根節點 return nextNode; }else{ if (p.lchild != null && p.lchild.data == node.data) { // 刪除節點在其父節點的左子樹上 p.lchild = nextNode; } else { p.rchild = nextNode; } } } return root; } public static void inOrder(Node root){ // 中序遍歷BST為單調遞增序列 if(root != null){ inOrder(root.lchild); System.out.print(root.data + " "); inOrder(root.rchild); } } private static class Node extends Object{ private Node lchild = null; private Node rchild = null; private int data; public Node(int data){ this.data = data; } } // 得到一組資料的中位數,以這樣的資料構造BST將會是平衡二叉樹,同時也是所有這些同樣資料(順序不一樣)構造的排序二叉樹中高度最小的哦 public static ArrayList<Integer> getMedians(int[] datas, int begin, int end) { Arrays.sort(datas); ArrayList<Integer> arr = new ArrayList<Integer>(); if (begin > end) { return arr; // 空arr } else if (begin == end) { arr.add(datas[begin]); } else { int medium = (begin + end) / 2; arr.add(datas[medium]); arr.addAll(getMedians(datas, begin, medium - 1)); arr.addAll(getMedians(datas, medium + 1, end)); } return arr; } public static int getDepth(Node root){ int ldepth = 0; // 左子樹高度 int rdepth = 0; // 右子樹高度 if(root == null){ // 空樹深度為0 return 0; } ldepth = getDepth(root.lchild); rdepth = getDepth(root.rchild); return (ldepth > rdepth ? ldepth : rdepth) + 1; } }