理论基础 —— 查找 —— 二叉排序树
【概述】
二叉排序樹(Binary Search Tree),又稱二叉查找樹,其本質是按一定的順序進行構造的二叉樹。
其遞歸定義如下:
- 若其左子樹不空,則左子樹上所有結點的值均小于根結點的值
- 若其右子樹不空,則右子樹上所有結點的值均大于根節(jié)點的值
- 其左右子樹也是二叉排序樹
從上述定義可以看出,二叉排序樹是記錄之間滿足一定次序的二叉樹,中序遍歷二叉排序樹可以得到一個按關鍵碼有序的序列。
折半查找判定樹就是一棵二叉排序樹:點擊這里
【實現(xiàn)類】
template<class T> struct Node{T data;Node *lchild,*rchild; }; template<class T> class BiSortTree{ public:BiSortTree(T a[],int n);//構造函數(shù)~BiSortTree(){release(root);}//析構函數(shù)void insertBST(Node<T> *&root,Node<T> *s);//插入結點void deleteBST(Node<T> *p,Node<T> *f);//刪除結點Node<T> *searchBST(Node<T> *bt,int k);//查找結點 private:Node<T> *root;//指向根節(jié)點的頭指針void release(Node<T> *bt);//析構函數(shù)調用 };【插入操作】
根據二叉排序樹的定義,向二叉排序樹中插入一個結點 s 的過程可用如下偽代碼描述:
從上述插入過程可以看出,插入的結點是作為葉結點插入到二叉排序樹中的,其過程是遞歸進行的。
template<class T> void BiSortTree<T>::insertBST(Node<T> *&root,Node<T> *s) {if(root==NULL)root=s;else if(s->data<root->data)insertBST(root->lchild,s);elseinsertBST(root->rchild,s); }【構造函數(shù)】
構造二叉排序樹的過程是從空的二叉排序樹開始,依次插入一個個結點,其構造過程可用如下偽代碼描述:
依次取每一個記錄 a[i],進行如下操作:
1)申請一個數(shù)據域為 a[i] 的結點 s,令結點 s 的左右指針域為空
2)調用插入操作的方法,將結點 s 插入二叉排序樹中
template<class T> BiSortTree<T>::BiSortTree(T a[],int n){for(int i=0;i<n;i++){Node<T> *s;s->data=a[i];s->lchild=NULL;s->rchild=NULL;insertBST(root,s);} }【刪除操作】
在二叉排序樹中,由于刪除結點時,刪除的可能是葉結點也可能是分支結點,因此在刪除時,需要重新修改指針,使得刪除一個結點后,仍能保證二叉排序樹的特性。
在二叉排序樹中的刪除操作中,設待刪除結點為 p,其父結點為 f,且 p 是 f 的左孩子,那么可分為以下三種情況進行討論:
1.p 為葉結點
當被刪除的結點為葉結點時,由于刪除后不影響二叉排序樹特性,因此只需將被刪除結點的父節(jié)點 f 的相應指針域改為空即可。
如下圖,有:f->lchild=NULL
2.p 只有左子樹 pl 或只有右子樹 pr
當被刪除的結點僅有一棵子樹時,需要將 pl 或 pr 替換為 f 的左子樹。
如下圖,有:f->lchild=p->lchild 或 f->rchild=p-rchild
3.p 既有左子樹又有右子樹
當被刪除的結點有兩棵子樹時,需要找其前驅(即:大于 p 的最小值 或 小于 p 的最大值)來將其代替,然后刪除該前驅。
綜上,刪除操作可用如下偽代碼描述:
1.若結點 p 是葉結點,則直接刪除結點 p
2.若結點 p 只有左子樹,則只需重接 p 的左子樹;若結點 p 只有右子樹,則只需重接 p 的右子樹
3.若結點 p 的左右子樹均不空,則:
? 1)查找結點 p 的右子樹上的最左下結點 s 及 s 雙親結點 f
? 2)將結點 s 數(shù)據域替換到被刪結點 p 的數(shù)據域
? 3)若結點 p 的右孩子無左子樹,則將 s 的右子樹接到 f 的右子樹上;否則,將 s 的右子樹接到結點 f 的左子樹上
? 4)刪除結點 s?
【查找操作】
由于二叉排序樹的定義,在二叉樹中查找給定值 k 的過程是:
- 若 root 是空樹,查找失敗
- 若 k=root->data,查找成功
- 若 k<root->data,在 root 的左子樹進行查找
- 若 k>root->data,在 root 的右子樹進行查找
上述過程一直持續(xù)到 k 被找到或者待查找的子樹為空,若待查找的子樹為空,則查找失敗。值得注意的是,當查找失敗時,恰好找到了以 k 為鍵值的新結點在二叉排序樹中的插入位置。
template<class T> Node<T> *BiSortTree<T>::searchBST(Node<T> *bt,int k){if(bt==NULL)return NULL;else if(bt->data==k)return bt;else if(k<bt->data)return searchBST(bt->lchild,k);elsereturn searchBST(bt->rchild,k); }【析構函數(shù)】
二叉排序樹的析構函數(shù)與二叉鏈表的析構函數(shù)相同
template<class T> void BiSortTree<T>::release(Node<T> *bt){if(bt!=NULL){release(bt->lchild);release(bt->rchild);delete bt;} }?
總結
以上是生活随笔為你收集整理的理论基础 —— 查找 —— 二叉排序树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理论基础 —— 索引 —— 2-3 树
- 下一篇: 信息学奥赛一本通(1012:计算多项式的