一、什麼是二叉搜索樹
二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於等於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於等於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹。
二、查詢
定義樹的結點類爲
class Node{ int k; Node left = null; Node right = null; Node p = null; }
查找過程,從樹的根節點開始查找,輸入樹的根節點和需要查找的k值,如果結點存在,返回指向關鍵字k的結點,否則返回null。
public Node TreeSearch(Node root,int k){ if(root==null||k==root.k) return root; if(k<root.k){ return TreeSearch(root.left,k); }else{ return TreeSearch(root.right,k); } }
三、插入
四、刪除插入和刪除會引起由二叉搜索樹的動態集合的變化。一定要修改數據結果來反映這個變化,但修改要保持二叉樹搜索樹性質成立。
public void TreeInsert(Node root,Node z){ Node y = null; Node x = root; while(x!=null){ y = x; if(z.k<x.k){ x = x.left; }else{ x = x.right; } } z.p = y; if(y==null){ root = z; }else if(z.k<y.k){ y.left = z; }else{ y.right = z; } }
刪除分爲三種情況
1、如果z沒有孩子結點,那麼知識簡單地將它刪除,並修改它的父結點,用null最爲孩子了替換z
2、如果z只有一個孩子,那麼將這個孩子提升到樹中的z的位置,並修改z的父結點,用z的孩子代替z
3、如果z有兩個孩子,那麼找z的後繼y(一定在z的右子樹中)並讓其佔據樹中z的位置,z原來額右子樹部分稱爲y的右子樹,並且z的左子樹稱爲y的新的左子樹。
爲了完成刪除操作,我們先來做一下準備工作。
最大關鍵字元素和最下關鍵字元素
/** * 獲得最小值元素 * @param x * @return */ public Node TreeMiniNum(Node x){ while(x.left!=null){ x = x.left; } return x; } /** * 獲得最大值元素 * @param x * @return */ public Node TreeMaxiNum(Node x){ while(x.right!=null){ x = x.right; } return x; }
前驅和後繼
一個結點的後繼是大於x.key的最小關鍵詞的結點,前驅是小於x.key的最大關鍵字的結點。
/** * 求後繼 * @param x * @return */ public Node TreeSuccessor(Node x){ if(x.right!=null){ return TreeMiniNum(x.right); } Node y = x.p; while(y!=null && x == y.right){ x = y; y = y.p; } return y; }
爲了在二叉搜索樹內移動子樹,定義一個子過程TRANSPLANT,它是用另一顆子樹替換一棵子樹併成爲其雙親的孩子結點。當TRANSPLANT用一顆以v爲根的子樹來替換一顆以u爲根的子樹時,結點u的雙親就變爲結點v的雙親,並最後v成爲u的雙親的相應孩子。
public void Transplant(Node root,Node u,Node v){ if(u.p==null) root = v; else if(u==u.p.left) u.p.left = v; else u.p.right = v; if(v!=null){ v.p = u.p; } }
下面是二叉搜索樹刪除結點z的刪除過程
public void TreeDelete(Node root,Node z){ //第一種情況 if(z.left==null) Transplant(root, z, z.right); else if(z.right == null) Transplant(root, z, z.left); //第二和第三種情況 else { Node y = TreeMiniNum(z.right); if(y.p!=z){//第三種情況 Transplant(root, y, y.right); y.right = z.right; y.right.p = y; } //z的後繼恰好爲z的有右孩子,第二種情況 Transplant(root, z, y); y.left = z.left; y.left.p = y; } }
在一顆高度爲h的二叉搜素樹上,實現動態集合操作Insert和Delete的運行時間均爲o(h)。
本文爲《算法導論》二叉搜索複習筆記