C++實現的二叉查詢樹
阿新 • • 發佈:2020-08-16
二叉排序樹(Binary Search Tree)又稱二叉排序樹(Binary Sort Tree),或者是一顆空二叉樹,或者是具有一下特性的二叉樹:
若它的左子樹不為空,則左子樹上的所有結點的值均小於根節點的值。
若它的右子樹不為空,則右子樹上的所有結點的值均小於根節點的值。
它的左右子樹又分別是二叉排序樹。
結點結構
template<typename T>
//樹結點結構
class BSTNode{
public:
T _key; //關鍵在字(鍵值)
BSTNode *_lchild; //左孩
BSTNode *_rchild; //右孩
BSTNode *_parent; // 雙親
//建構函式
BSTNode(T key ,BSTNode *lchild,BSTNode *rchild,BSTNode *parent):
_key(key),_lchild(lchild),_rchild(rchild),_parent(parent){};
//使用建構函式初始化表列對以上四個資料進行初始化。
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
二叉查詢樹的操作:
template<typename T>
class BSTree{
private:
BSTNode<T> *_Root ; //根結點
public:
BSTree():_Root(NULL){};
~BSTree(){};
void insert (T key);//二叉樹的插入
BSTNode<T>* search (T key) ;//二叉樹的查詢
void preOrder() ; //先序輸出
void inOrder() ; //中序輸出
void postOrder() ; //後序輸出
BSTNode<T>* minimumNode();//查詢最小的節點
BSTNode<T>* maximumNode ();//查詢最大的節點
T minimumKey();//查詢最小的鍵值
T maximumKey();//查詢最小的鍵值
void print();//列印二叉樹
void remove(T key);
BSTNode<T>* predecessor(BSTNode<T>* x);//查詢某個結點的前驅
BSTNode<T>* sucessor(BSTNode<T>* x); //查詢某個結點的後繼
void destory ();
//內部使用函式,供外部介面呼叫
private:
void insert(BSTNode<T>* &tree,BSTNode<T>* z);
BSTNode<T>* search(BSTNode<T>* &tree,T key) const;
void preOrder(BSTNode<T>*&tree) const;
void inOrder(BSTNode<T>*&tree) const;
void postOrder(BSTNode<T>*&tree) const;
BSTNode<T>* minimumNode(BSTNode<T> *&tree);
BSTNode<T>* maximumNode (BSTNode<T> *&tree);
void print(BSTNode<T>*& tree);
BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
void destory(BSTNode<T>*& tree);
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
BSTree類包含了一個BSTNode指標資料成員,代表二叉查詢樹的根結點。類種封裝了二叉查詢樹常用的操作介面,包括:
插入操作:也是建立二叉查詢樹的方法。
遍歷演算法:包括前序、中序、後序(遞迴實現)。
查詢操作:包括查詢某個結點、查詢最小結點、查詢最大結點、查詢最小值、查詢最大值。
刪除操作。
銷燬操作。
列印操作:列印說明二叉樹的結構。
BSTree類大部分的函式都有兩個過載版本,一個僅供類內部使用(privata宣告),另一個則為類使用者使用的公用介面(public宣告)。
前序遍歷:
/*
*
*前序遍歷演算法
*BSTree類內部呼叫函式
*
*/
template<typename T>
void BSTree<T>::preOrder(BSTNode<T>*&tree) const
{
if(tree)
{
cout<<tree->_key<<" ";
preOrder(tree->_lchild);
preOrder(tree->_rchild);
}
}
/*
*介面
*
*/template<typename T>
void BSTree<T>::postOrder()
{
postOrder(_Root);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
中序遍歷
/*
*
*中序遍歷演算法
*類內部呼叫函式
*
*/
template <typename T>
void BSTree<T>::inOrder(BSTNode<T>*&tree) const
{
if(tree)
{
inOrder(tree->_lchild);
cout<<tree->_key<<" ";
inOrder(tree->_rchild);
}
}
/*
*
*介面
*
*/
template<typename T>
void BSTree<T>::inOrder()
{
inOrder(_Root);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
後序遍歷
/*
*
*後序遍歷演算法
*類內部呼叫函式
*
*/
template <typename T>
void BSTree<T>::postOrder(BSTNode<T>*&tree) const
{
if(tree)
{
postOrder(tree->_lchild);
postOrder(tree->_rchild);
cout<<tree->_key<<" ";
}
}
/*
*
*介面
*
*/
template<typename T>
void BSTree<T>::postOrder()
{
postOrder(_Root);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
2.2二叉查詢樹的插入
構建查詢二叉樹通過二叉查詢樹的插入操作來進行。插入時嚴格按照查詢二叉樹的定義來進行,其插入演算法的基本過程可以分解為:
根結點為空則進行插入。
值比根結點小,在根結點的左子樹進行插入。
值比根結點大,在根節點的右子樹進行插入。
本文采用非遞迴演算法實現插入操作。
/*
*插入操作
*非遞迴實現
*內部使用函式
*/
template<typename T>
void BSTree<T> ::insert(BSTNode<T>* &tree,BSTNode<T>* z)
{
BSTNode<T>* parent = NULL;
BSTNode<T>* temp = tree;
//尋找插入點
while(temp!=NULL)
{
parent= temp;
if(z->_key>temp->_key)
temp= temp->_rchild;
else
temp=temp->_lchild;
}
z->_parent = parent;
if(parent==NULL) //如果樹本來就是空樹,則直接把z節點插入根節點
tree = z;
else if(z->_key>parent->_key) //如果z的值大於其雙親,則z為其雙親的右孩
parent->_rchild = z;
else
parent->_lchild = z;
}
/*
*
*介面
*/
template <typename T>
void BSTree<T>::insert(T key)
{
//建立一個新的節點,使用建構函式初始化
BSTNode<T>* z= new BSTNode<T>(key,NULL,NULL,NULL);
if(!z) //如果建立失敗則返回
return ;
//呼叫內部函式進行插入
insert(_Root,z);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
2.3 二叉查詢樹的查詢
2.3.1 查詢某個值的結點
這裡提供遞迴與非遞迴演算法實現查詢操作。
/*
*查詢操作
*非遞迴實現
*內部使用函式
*/
template <typename T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* &tree,T key) const
{
BSTNode<T>* temp = tree;
while(temp != NULL)
{
if(temp->_key == key)
return temp;
else if(temp->_key>key)
temp = temp->_lchild;
else
temp = temp->_rchild;
}
return NULL;
}
查詢演算法的遞迴實現
//template<typename T>
//BSTNode<T>* BSTree<T>::search( BSTNode<T>* &tree,T key) const
//{
// if(!tree)
// {
// if(tree->_key==key)
// return tree;
// if(tree->_key>key)
// return search(tree->_lchild,key);
// if(tree->_key<z->_key)
// return search(tree->_rchild,key);
// }
// return NULL;
//}
/*
*介面
*/
template <typename T>
BSTNode<T> * BSTree<T>::search(T key)
{
return search(_Root,key);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
2.3.2查詢二叉查詢樹值最小的結點
/*
*
*查詢最小的結點
*內部呼叫函式
*
*/
template <typename T>
BSTNode<T>* BSTree<T>::minimumNode(BSTNode<T>*&tree)
{
BSTNode<T>* temp = tree;
while(temp->_lchild)
{
temp= temp->_lchild;
}
return temp;
}
/*
*介面
*/
template<typename T>
BSTNode<T>* BSTree<T>::minimumNode()
{
return minimumNode(_Root);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2.3.3查詢二叉查詢樹中值最大的結點
/*
*
*查詢鍵值最大的節點
*內部呼叫函式
*非遞迴實現
*/
template<typename T>
BSTNode<T>* BSTree<T>::maximumNode(BSTNode<T>* &tree)
{
BSTNode<T>* temp=tree;
while(temp->_rchild)
{
temp= temp->_rchild;
}
return temp;
}
/*
*介面
*/
template<typename T>
BSTNode<T>* BSTree<T>::maximumNode()
{
return maximumNode(_Root);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
2.3.4查詢二叉查詢樹中最小的值
/*
*
*查詢最小的鍵值
*外部介面函式
*呼叫內部函式minimumNode實現
*/
template<typename T>
T BSTree<T>::minimumKey()
{
BSTNode<T> *temp = minimumNode(_Root);
return temp->_key;
}
2.4.5查詢二叉查詢樹中最大的值
/*
*
*查詢最大的鍵值
*外部介面函式
*呼叫內部函式maximumKey
*/
template<typename T>
T BSTree<T>::maximumKey()
{
BSTNode<T> *temp = maximumNode(_Root);
return temp->_key;
}
2.3列印查詢二叉樹
該操作把二叉樹中每個結點的父結點、左右孩子結點的資訊描述出來。
/*
*
*列印函式
*打印出平衡二叉樹
*BStree內部函式
*/
template<typename T>
void BSTree<T>::print(BSTNode<T>*& tree)
{
if(tree) //如果tree不為空
{
if(tree->_lchild) //結點有左孩子
{
cout<<"節點"<<tree->_key<<"有左孩子為"<<tree->_lchild->_key<<endl;
}
else
cout<<"節點"<<tree->_key<<"無左孩子"<<endl;
if(tree->_rchild)
{
cout<<"節點"<<tree->_key<<"有右孩子為"<<tree->_rchild->_key<<endl;
}
else
cout<<"節點"<<tree->_key<<"無右孩子"<<endl;
print(tree->_lchild);
print(tree->_rchild);
}
}
/*
*介面
*/
template<typename T>
void BSTree<T>::print()
{
print(_Root);
}
2.4查詢給定結點的前驅結點
/*
*查詢某個節點x的前驅
*
*介面
*
*/
template <typename T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* x)
{
//如果x是最小的結點,則它沒有前驅
if(x->_key == minimumNode(_Root)->_key)
return NULL;
//否則
//先獲取二叉樹中鍵值與x的鍵值相同的結點y
BSTNode <T> * y = NULL;
y = search(_Root,x->_key);
if(y==NULL) return NULL;
//如果y有左孩子,則x的前驅為“以x的左孩為根的子樹的最大結點”
if(y->_lchild!=NULL)
return maximumNode(y->_lchild);
//如果y沒有左孩子,則x有兩種可能:
//1.y是一個右孩子,此時x的前驅為其雙親節點
BSTNode