一、二叉排序樹的定義 二叉排序樹(Binary Sort Tree)又稱二叉查找(搜索)樹(Binary Search Tree)。其定義爲:二叉排序樹或者是空樹,或者是知足以下性質的二叉樹: ①若它的左子樹非空,則左子樹上全部結點的值均小於根結點的值; ②若它的右子樹非空,則右子樹上全部結點的值均大於根結點的值; ③左、右子樹自己又各是一棵二叉排序樹。 上述性質簡稱二叉排序樹性質(BST性質),故二叉排序樹其實是知足BST性質的二叉樹。 二、二叉排序樹的特色 由BST性質可得: (1) 二叉排序樹中任一結點x,其左(右)子樹中任一結點y(若存在)的關鍵字必小(大)於x的關鍵字。 (2) 二叉排序樹中,各結點關鍵字是唯一的。 注意: 實際應用中,不能保證被查找的數據集中各元素的關鍵字互不相同,因此可將二叉排序樹定義中BST性質(1)裏的"小於"改成"大於等於",或將BST性質(2)裏的"大於"改成"小於等於",甚至可同時修改這兩個性質。 (3) 按中序遍歷該樹所獲得的中序序列是一個遞增有序序列。 ①二叉排序樹插入新結點的過程 在二叉排序樹中插入新結點,要保證插入後仍知足BST性質。其插入過程是: (a)若二叉排序樹T爲空,則爲待插入的關鍵字key申請一個新結點,並令其爲根; (b)若二叉排序樹T不爲空,則將key和根的關鍵字比較: (i)若兩者相等,則說明樹中已有此關鍵字key,無須插入。 (ii)若key<T→key,則將key插入根的左子樹中。 (iii)若key>T→key,則將它插入根的右子樹中。 子樹中的插入過程與上述的樹中插入過程相同。如此進行下去,直到將key做爲一個新的葉結點的關鍵字插入到二叉排序樹中,或者直到發現樹中已有此關鍵字爲止。 注意: 輸入序列決定了二叉排序樹的形態。 二叉排序樹的中序序列是一個有序序列。因此對於一個任意的關鍵字序列構造一棵二叉排序樹,其實質是對此關鍵字序列進行排序,使其變爲有序序列。"排序 樹"的名稱也由此而來。一般將這種排序稱爲樹排序(Tree Sort),能夠證實這種排序的平均執行時間亦爲O(nlgn)。 對相同的輸入實例,樹排序的執行時間約爲堆排序的2至3倍。所以在通常狀況下,構造二叉排序樹的目的並不是爲了排序,而是用它來加速查找,這是由於在一 個有序的集合上查找一般比在無序集合上查找更快。所以,人們又經常將二叉排序樹稱爲二叉查找樹。 public class BinarySortTree { private int data; private BinarySortTree lChild; private BinarySortTree rChild; public BinarySortTree(int data){ this.data = data; lChild = null; rChild = null; } public BinarySortTree(){ this.data = 0; lChild = null; rChild = null; } /** * 方法名稱:createTree() * 方法描述:根據數組中的數據信息生成一個二叉查找樹 * @param * @return String * @Exception */ public BinarySortTree createTree(int[] datas){ BinarySortTree root = new BinarySortTree(datas[0]); for(int i=1;i<datas.length;i++){ insertTree(root, datas[i]); } return root; } /** * 方法名稱:insertTree() * 方法描述:向二叉排序樹種插入數據 * @param * @return String * @Exception */ private void insertTree(BinarySortTree root, int data) { // TODO Auto-generated method stub BinarySortTree child = null; if(root != null){ if(data < root.data){ if(root.lChild == null){ child = new BinarySortTree(data); root.lChild = child; }else{ insertTree(root.lChild, data); } }else if(data > root.data){ if(root.rChild == null){ child = new BinarySortTree(data); root.rChild = child; }else{ insertTree(root.rChild, data); } }else{ return ; } } } /** * 方法名稱:inOrder() * 方法描述:中序遍歷 * @param * @return String * @Exception */ public void inOrder(BinarySortTree root){ if(root != null){ inOrder(root.lChild); System.out.print(root.data + " "); inOrder(root.rChild); } } /** * 方法名稱:search() * 方法描述:查找元素 * @param * @return String * @Exception */ public boolean search(BinarySortTree root, int data){ if(root != null){ if(root.data == data){ return true; }else if(root.data < data){ return search(root.rChild, data); }else { return search(root.lChild, data); } } return false; } /** * 方法名稱:delete() * 方法描述:刪除節點 * @param 採用遞歸的方式進行刪除 * @return String * @Exception */ public void delete(BinarySortTree root, int data){ if(root != null){ if(root.data < data){ //查找右孩子 delete(root.rChild,data); }else if(root.data > data){ delete(root.lChild,data); }else{ deleteNode(root); } } } /** * 方法名稱:deleteNode() * 方法描述:執行具體的刪除操做 * @param * @return String * @Exception */ private void deleteNode(BinarySortTree p) { // TODO Auto-generated method stub if(p != null){ //若是節點有左子樹 /*1。若p有左子樹,找到其左子樹的最右邊的葉子結點r,用該葉子結點r來替代p,把r的左孩子 做爲r的父親的右孩子。 2。若p沒有左子樹,直接用p的右孩子取代它。*/ if(p.lChild != null){ BinarySortTree r = p.lChild; BinarySortTree prev = p.lChild; while(r.rChild != null){ prev = r; r = r.rChild; } p.data = r.data; //若r不是p的左子樹,p的左子樹不變,r的左子樹做爲r的父節點的右孩子節點 if(prev != r){ prev.rChild = r.lChild; }else{ //若r是p的左子樹,則p的左子樹只想r的左子樹 p.lChild = r.lChild; } }else{ p = p.rChild; } } } public static void main(String[] args){ BinarySortTree root = new BinarySortTree(); int[] datas = {14,9,17,16};//{63,90,70,55,67,42,98,83,10,45,58}; root = root.createTree(datas); root.inOrder(root); System.out.println(); System.out.println(root.search(root, 98)); root.delete(root, 17); root.inOrder(root); } }
其中刪除部分思想參考該文:blog.csdn.net/arcsinsin/article/details/10238505 java
文字部分的引用文章爲:http://sjjp.tjuci.edu.cn/sjjg/DataStructure/DS/web/chazhao/chazhao9.1.1.htm web