標籤:style blog http color 資料 2014
二叉排序樹(Binary Sort Tree)又稱二叉尋找樹,是一種排序和尋找都很有用的特殊二叉樹。
BST 滿足 左節點的值<根節點的值<右節點的值。根據這個原理,我們可以推斷:BST的中序遍曆必定是嚴格遞增的。
一棵二叉樹,是一棵BST。我們可以明顯看到他的中序遍曆為09,17,23,45,53,60,70,75,78,88,94。(因為左<中<右)
下面是BST的實現,包括BST的插入,建立,刪除,遍曆
//BST.h#include<iostream>using namespace std;template<typename T>struct node{ T key; //char word;};template<typename T>struct BSTNode{ node<T> data; BSTNode<T> *lchild; BSTNode<T> *rchild;};template<typename T>class BSTree{private: BSTNode<T> *bt;//根指標public: BSTree();//建構函式 ~BSTree();//解構函式 BSTNode<T>* & GetRoot();//得到跟節點 void Clear(BSTNode<T>* &p);//刪除節點,釋放空間 bool BSTInsert(BSTNode<T>* &p,T key);//在p指向的二叉樹中有序插入 資料元素為key的節點 void Create(int n);//建立含有n個元素的BST void PreTraBST(BSTNode<T> *p);//前序走訪 void InTraBST(BSTNode<T> *p);//中序遍曆,輸出的BST是從小到大排列的 void SearchBST(BSTNode<T> *p,T key);//在p指向的二叉樹中尋找 是否存在資料元素key int Delete(BSTNode<T> * &p);//刪除節點p int DeleteBST(BSTNode<T>* &p,T key);//在p指向的BST中刪除資料元素key,並保證刪除後的二叉樹還是BST};template<typename T>BSTree<T>::BSTree(){ bt=NULL;}template<typename T>BSTree<T>::~BSTree(){ BSTNode<T> *p; p=bt; Clear(p);}template<typename T>BSTNode<T>* & BSTree<T>::GetRoot(){ return bt;}template<typename T>void BSTree<T>::Clear(BSTNode<T> * &p){ if(p) { Clear(p->lchild); Clear(p->rchild); } getchar(); delete p; cout<<"刪除節點"<<p<<"的空間"<<endl;}template<typename T>bool BSTree<T>::BSTInsert(BSTNode<T>* &p,T key)//在p指向的二叉樹中有序插入資料元素key{ if(p==NULL) //p為空白樹,建立資料元素為key的新節點,並將p指向該節點 { BSTNode<T> *s=new BSTNode<T>; s->data.key=key; s->lchild=s->rchild=NULL; p=s; return true; } else if(key>p->data.key)//key 大於節點p->data.key,遞迴遍曆右子樹。BST的右子樹一定大於左子樹 BSTInsert(p->rchild,key); else if(key<p->data.key)//key 小於節點p->data.key,遍曆左子樹。 BSTInsert(p->lchild,key); else if(key==p->data.key) { cout<<"插入資料已存在"<<endl; return false; }}template<typename T>void BSTree<T>::Create(int n){ T key; bt=NULL; cout<<"輸入"<<n<<"個不同的資料元素"<<endl; for(int i=0;i<n;i++) { cin>>key; BSTInsert(bt,key); }}template<typename T>void BSTree<T>::PreTraBST(BSTNode<T> *p){ if(p) { cout<<p->data.key<<" "; PreTraBST(p->lchild); PreTraBST(p->rchild); }}template<typename T>void BSTree<T>::InTraBST(BSTNode<T> *p) //中序輸出時資料元素一定是按升序排列的{ if(p) { InTraBST(p->lchild); cout<<p->data.key<<" "; InTraBST(p->rchild); }}template<typename T>void BSTree<T>::SearchBST(BSTNode<T> *p,T key)//在BST中尋找資料元素key 是否存在,存在則找出其中的p,並且刪除{ if(p==NULL||p->data.key==key) { if(p==NULL) { cout<<"尋找的資料元素不存在"<<endl; } else if(p->data.key==key) { cout<<"找到資料元素"<<key<<endl; } } else if(key>p->data.key) { SearchBST(p->rchild,key); } else if(key<p->data.key) { SearchBST(p->lchild,key); } }template<typename T>int BSTree<T>::Delete(BSTNode<T>* &p)//刪除節點p{ BSTNode<T> *q,*s; if(p->rchild==NULL)//待刪除的節點p沒有右子樹 { q=p; p=p->lchild; cout<<"成功刪除"<<endl; delete q; } else if(p->lchild==NULL)//待刪除的節點p沒有左子樹 { q=p; p=p->rchild; cout<<"成功刪除"<<q->data.key<<endl; delete q; } else if(p->lchild==NULL&&p->rchild==NULL) { delete p; cout<<"成功刪除"<<endl; } else//待刪除的節點p的左右節點都存在 { q=p; s=p->lchild; while(s->rchild)//在p節點的左子樹中尋找其前驅節點。即最右節點。 { q=s; s=s->rchild;//最終s指向待刪除節點的前驅節點 } p->data=s->data;//將前驅節點賦值給p節點 if(q!=p) q->rchild=s->lchild; else q->lchild=s->lchild; delete s; cout<<"成功刪除"<<endl; } return true;}template<typename T>int BSTree<T>::DeleteBST(BSTNode<T>* &p,T key){ if(p==NULL) { cout<<"二叉樹為空白,無法刪除"<<endl; return false; } else { if(key==p->data.key) return Delete(p); else if(key>p->data.key) return DeleteBST(p->rchild,key); else return DeleteBST(p->lchild,key); }}
//BST-main.cpp#include<iostream>using namespace std;#include"BST.h"int main(void){ int n,key,flag; BSTree<int> bst; cout<<"輸入二叉樹的資料元素個數:"; cin>>n; bst.Create(n);//Create建立的是一個排序二叉樹 cout<<"先序遍曆輸出:"; bst.PreTraBST(bst.GetRoot()); cout<<endl; cout<<"中序遍曆輸出:";//中序遍曆一定是有序的 bst.InTraBST(bst.GetRoot()); cout<<endl; cout<<"輸入要尋找的元素:"; cin>>key; bst.SearchBST(bst.GetRoot(),key); flag=1; while(flag) { cout<<"輸入要刪除的元素(-1為結束標誌):"; cin>>key; if(key!=-1) { bst.DeleteBST(bst.GetRoot(),key); } else flag=0; cout<<"先序遍曆輸出:"; bst.PreTraBST(bst.GetRoot()); cout<<endl; cout<<"中序遍曆輸出:";//中序遍曆一定是有序的 bst.InTraBST(bst.GetRoot()); cout<<endl; } getchar();}
測試結果如下:
關於BST 刪除資料元素的理解
1.待刪除的節點p沒有右子樹 p->rchild==NULL
2.待刪除的節點p沒有左子樹 p->lchild==NULL
3.左右子節點都不存在 p->lchild==NULL&&p->rchild==NULL
直接刪除
4.左右子節點都存在 p->lchild!=NULL&&p->rchild!=NULL
4.1 q!=p 其中s指向待刪除節點的前驅節點,然後用77替換78,並將75指向76
4.2 p==q 將節點70賦值給節點80