BST是一种特殊的二叉树,它的遍历方法和二叉树相同,分为前序遍历、中序遍历和后序遍历,这3种遍历的实现(递归和迭代)我在前面的文章已经介绍过了,有兴趣可以参考一下。
二叉树的迭代法前序遍历的两种方法
二叉树的迭代法后序、中序遍历
二叉树的非递归(迭代)统一实现“前中后序遍历”详解
二叉树的层序遍历
定义好3个结构、类:
/******************二叉查找树节点键值结构************************/
template <typename Type>
struct Element
{
friend class BstNode<Type>;
friend class Bst<Type>;
public:
Element(){}
Element(Type _key):key(_key){}
//private:
Type key;//键值
//可以添加更多数据
};
/******************二叉查找树节点类************************/
template <typename Type>
class BstNode
{
friend class Bst<Type>;
public:
BstNode():leftChild(nullptr), rightChild(nullptr){};
BstNode(Element<Type> _content) :leftChild(nullptr), rightChild(nullptr)
{
content.key = _content.key;
};
//private:
Element<Type> content;
BstNode<Type> *leftChild;
BstNode<Type> *rightChild;
};
/******************二叉查找树类************************/
template <typename Type>
class Bst
{
public:
Bst(BstNode<Type> *_root = nullptr) :root(_root){}
void Insert(const Element<Type>& _data);//插入
BstNode<Type>* Search(const Element<Type>& _data);//递归查找
BstNode<Type>* Search(BstNode<Type>* node, const Element<Type>& _data);
BstNode<Type>* IterSearch(const Element<Type>& _data);//迭代查找
BstNode<Type>* FindMax();//查找子树的最大节点
BstNode<Type>* FindMax(BstNode<Type>* node);
BstNode<Type>* FindMin();//查找子树的最小节点
BstNode<Type>* FindMin(BstNode<Type>* node);
void Delete(const Element<Type>& _data);//删除
void InOrder();//中序遍历
void InOrder(BstNode<Type>* node);
void LevelOrder();//层序遍历
void LevelOrder(BstNode<Type>* node);
private:
BstNode<Type>* FindParent(BstNode<Type>* node);
BstNode<Type> *root;
};
代码中均有详细注释,如下:
template <typename Type>
void Bst<Type>::Insert(const Element<Type>& _data)
{
BstNode<Type> *newNode = new BstNode<Type>(_data);
BstNode<Type> *cur = root;
BstNode<Type> *tmp = root;
//若bst树为空,则插入的节点就是根节点
if (cur == nullptr)
root = newNode;
//若bst树不空
else{
//1.找到连接newNode的父节点
while (cur){
tmp = cur;//tmp就是保存newNode的父节点
if (newNode->content.key < cur->content.key){
cur = cur->leftChild;
}
else if(newNode->content.key > cur->content.key){
cur = cur->rightChild;
}
else{
throw "Error";
}
}
//2.确定newNode作为左节点还是右节点
if (newNode->content.key < tmp->content.key){
tmp->leftChild = newNode;
}
else if (newNode->content.key > tmp->content.key){
tmp->rightChild = newNode;
}
else{ ; }
}
}
我在这里给出递归和迭代两种方法:
代码如下:
template <typename Type>
BstNode<Type>* Bst<Type>::IterSearch(const Element<Type>& _data)
{
BstNode<Type> *cur = root;
while (cur){
if (cur->content.key == _data.key)
return cur;
else if (_data.key < cur->content.key)
cur = cur->leftChild;
else if (_data.key > cur->content.key)
cur = cur->rightChild;
else{}
}
return nullptr;
}
递归法需要用到重载。一个参数的Search函数是给类外部调用;由于使用递归调用,所以重载Search函数,增加一个表示节点类的参数。两个参数的Search函数应该作为类内部的私有成员函数。
BstNode<Type>* Search(const Element<Type>& _data);//递归查找
BstNode<Type>* Search(BstNode<Type>* node, const Element<Type>& _data);
代码如下:
template <typename Type>
BstNode<Type>* Bst<Type>::Search(const Element<Type>& _data)
{
return Search(root,_data);
}
template <typename Type>
BstNode<Type>* Bst<Type>::Search(BstNode<Type>* node, const Element<Type>& _data)
{
if (node == nullptr)
return nullptr;
if (_data.key < node->content.key)
return Search(node->leftChild,_data);
else if (_data.key > node->content.key)
return Search(node->rightChild, _data);
else
return node;
}
FinMax()函数和FindMin()函数都重载了。原因是对外部而言,只需提供无参的函数,返回BST的最大值和最小值节点即可,但是对我们实现功能,是必须输入节点参数的。
BstNode<Type>* FindMax();//查找子树的最大节点
BstNode<Type>* FindMax(BstNode<Type>* node);
BstNode<Type>* FindMin();//查找子树的最小节点
BstNode<Type>* FindMin(BstNode<Type>* node);
查找最大值节点FinMax(),注意,一颗BST的最大值节点永远是在树的最右边
template <typename Type>
BstNode<Type>* Bst<Type>::FindMax()
{
return FindMax(root);
}
template <typename Type>
BstNode<Type>* Bst<Type>::FindMax(BstNode<Type>* node)
{
BstNode<Type> *cur = node;
if (!cur) return nullptr;//node为空,直接返回
while (cur->rightChild)
cur = cur->rightChild;
return cur;
}
查找最大值节点FinMin(),注意,一颗BST的最小值节点永远是在树的最左边
template <typename Type>
BstNode<Type>* Bst<Type>::FindMin()
{
return FindMin(root);
}
template <typename Type>
BstNode<Type>* Bst<Type>::FindMin(BstNode<Type>* node)
{
BstNode<Type> *cur = node;
if (!cur) return nullptr;//node为空,直接返回
while (cur->leftChild)
cur = cur->leftChild;
return cur;
}
由于删除操作较为复杂,我在数据结构——详解二叉查找树(BST)的删除操作单独详细的描述了删除的操作,所以我在这里直接贴出代码:
template <typename Type>
void Bst<Type>::Delete(const Element<Type>& _data)
{
BstNode<Type> *deleteNode = nullptr;
BstNode<Type> *deleteNodeParent = nullptr;
BstNode<Type> *minNode = nullptr;
BstNode<Type> *maxNode = nullptr;
deleteNode = Search(_data);
if (!deleteNode) return;//deleteNode为空,表明BST中没有元素为_data的节点,直接返回
if (deleteNode->leftChild){//deleteNode有左子树,得到deleteNode左子树的最大值节点
maxNode = FindMax(deleteNode->leftChild);
}
if (deleteNode->rightChild){//deleteNode有右子树,得到deleteNode右子树的最小值节点
minNode = FindMin(deleteNode->rightChild);
}
deleteNodeParent = FindParent(deleteNode);//找到deleteNode节点的父节点
//maxNode和minNode的节点为空,表明deleteNode是一个叶子节点
if (!maxNode && !minNode){
if (deleteNodeParent->leftChild == deleteNode)
deleteNodeParent->leftChild = nullptr;
else
deleteNodeParent->rightChild = nullptr;
delete deleteNode;
}
//表明deleteNode最少有一个子树不空
else{
//1.将tmp节点的父节点和tmp的子节点连接
BstNode<Type> *tmp = (maxNode == nullptr) ? minNode : maxNode;
BstNode<Type> * tmpParent = FindParent(tmp);
if (tmp->leftChild){//左孩子不空,右孩子必空.此情况对应的是 maxNode
if (tmpParent->leftChild == tmp)//tmp是左孩子
tmpParent->leftChild = tmp->leftChild;
else
tmpParent->rightChild = tmp->leftChild;
}
else{//右孩不空,左孩子必空,此情况对应的是 minNode
if (tmpParent->leftChild == tmp)
tmpParent->leftChild = tmp->rightChild;
else
tmpParent->rightChild = tmp->rightChild;
}
//2.将tmp节点和deleteNode的父节点连接
if (deleteNodeParent == nullptr)
root = tmp;
else{
if (tmp->content.key < deleteNodeParent->content.key)
deleteNodeParent->leftChild = tmp;
else
deleteNodeParent->rightChild = tmp;
}
//3.将tmp节点的左右孩子连接上deleteNode的左右孩子
tmp->leftChild = deleteNode->leftChild;
tmp->rightChild = deleteNode->rightChild;
delete deleteNode;
}
}
查找父节点的私有成员函数:
template <typename Type>
BstNode<Type>* Bst<Type>::FindParent(BstNode<Type>* node)
{
//node = root.表明node无父节点
if (root == node)
return nullptr;
BstNode<Type>* cur = root;
while (cur && root){
//返回父节点
if (cur->leftChild == node || cur->rightChild == node)
return cur;
//cur节点不是node的父节点,根据key确定从cur的左子树找还是右子树找
if (node->content.key < cur->content.key)
cur = cur->leftChild;
else
cur = cur->rightChild;
}
return nullptr;
}
前、中、后序遍历和层序遍历在前面文章中均有详细的讲解,本文不做探讨。下面直接给出前中序遍历和层序遍历以便测试:
/******************中序遍历InOrder************************/
template <typename Type>
void Bst<Type>::InOrder()
{
InOrder(root);
}
template <typename Type>
void Bst<Type>::InOrder(BstNode<Type>* node)
{
if (node == nullptr)
return;
InOrder(node->leftChild);
std::cout << node->content.key << std::endl;
InOrder(node->rightChild);
}
/******************层序遍历InOrder************************/
template <typename Type>
void Bst<Type>::LevelOrder()
{
LevelOrder(root);
}
template <typename Type>
void Bst<Type>::LevelOrder(BstNode<Type>* node)
{
queue<BstNode<Type>*> q;
q.push(node);
while (!q.empty()){
int size = q.size();
std::cout << "[";
for (int i = 0; i < size; i++){
BstNode<Type>* tmp = q.front();
q.pop();
std::cout << tmp->content.key << " ";
if (tmp->leftChild) q.push(tmp->leftChild);
if (tmp->rightChild) q.push(tmp->rightChild);
}
std::cout <<"]" <<std::endl;
}
}
Bst.h如下:
#ifndef _BST_H
#define _BST_H
#include
template <typename Type>
class BstNode;
template <typename Type>
class Bst;
/******************二叉查找树节点键值结构************************/
template <typename Type>
struct Element
{
friend class BstNode<Type>;
friend class Bst<Type>;
public:
Element(){}
Element(Type _key):key(_key){}
//private:
Type key;//键值
//可以添加更多数据
};
/******************二叉查找树节点类************************/
template <typename Type>
class BstNode
{
friend class Bst<Type>;
public:
BstNode():leftChild(nullptr), rightChild(nullptr){};
BstNode(Element<Type> _content) :leftChild(nullptr), rightChild(nullptr)
{
content.key = _content.key;
};
//private:
Element<Type> content;
BstNode<Type> *leftChild;
BstNode<Type> *rightChild;
};
/******************二叉查找树类************************/
template <typename Type>
class Bst
{
public:
Bst(BstNode<Type> *_root = nullptr) :root(_root){}
void Insert(const Element<Type>& _data);//插入
BstNode<Type>* Search(const Element<Type>& _data);//递归查找
BstNode<Type>* Search(BstNode<Type>* node, const Element<Type>& _data);
BstNode<Type>* IterSearch(const Element<Type>& _data);//迭代查找
BstNode<Type>* FindMax();//查找子树的最大节点
BstNode<Type>* FindMax(BstNode<Type>* node);
BstNode<Type>* FindMin();//查找子树的最小节点
BstNode<Type>* FindMin(BstNode<Type>* node);
void Delete(const Element<Type>& _data);//删除
void InOrder();//中序遍历
void InOrder(BstNode<Type>* node);
void LevelOrder();//层序遍历
void LevelOrder(BstNode<Type>* node);
private:
BstNode<Type>* FindParent(BstNode<Type>* node);
BstNode<Type> *root;
};
/******************二叉查找树成员函数************************/
/******************插入Insert************************/
template <typename Type>
void Bst<Type>::Insert(const Element<Type>& _data)
{
BstNode<Type> *newNode = new BstNode<Type>(_data);
BstNode<Type> *cur = root;
BstNode<Type> *tmp = root;
//若bst树为空,则插入的节点就是根节点
if (cur == nullptr)
root = newNode;
//若bst树不空
else{
//1.找到连接newNode的父节点
while (cur){
tmp = cur;//tmp就是保存newNode的父节点
if (newNode->content.key < cur->content.key){
cur = cur->leftChild;
}
else if(newNode->content.key > cur->content.key){
cur = cur->rightChild;
}
else{
throw "Error";
}
}
//2.确定newNode作为左节点还是右节点
if (newNode->content.key < tmp->content.key){
tmp->leftChild = newNode;
}
else if (newNode->content.key > tmp->content.key){
tmp->rightChild = newNode;
}
else{ ; }
}
}
/******************递归查找Search************************/
template <typename Type>
BstNode<Type>* Bst<Type>::Search(const Element<Type>& _data)
{
return Search(root,_data);
}
template <typename Type>
BstNode<Type>* Bst<Type>::Search(BstNode<Type>* node, const Element<Type>& _data)
{
if (node == nullptr)
return nullptr;
if (_data.key < node->content.key)
return Search(node->leftChild,_data);
else if (_data.key > node->content.key)
return Search(node->rightChild, _data);
else
return node;
}
/******************迭代查找IterSearch************************/
template <typename Type>
BstNode<Type>* Bst<Type>::IterSearch(const Element<Type>& _data)
{
BstNode<Type> *cur = root;
while (cur){
if (cur->content.key == _data.key)
return cur;
else if (_data.key < cur->content.key)
cur = cur->leftChild;
else if (_data.key > cur->content.key)
cur = cur->rightChild;
else{ ; }
}
return nullptr;
}
/******************查找最大值节点************************/
template <typename Type>
BstNode<Type>* Bst<Type>::FindMax()
{
return FindMax(root);
}
template <typename Type>
BstNode<Type>* Bst<Type>::FindMax(BstNode<Type>* node)
{
BstNode<Type> *cur = node;
if (!cur) return nullptr;//node为空,直接返回
//cur = cur->leftChild;//cur指向node的左子树的父节点
while (cur->rightChild)
cur = cur->rightChild;
return cur;
}
/******************查找最小值节点************************/
template <typename Type>
BstNode<Type>* Bst<Type>::FindMin()
{
return FindMin(root);
}
template <typename Type>
BstNode<Type>* Bst<Type>::FindMin(BstNode<Type>* node)
{
BstNode<Type> *cur = node;
if (!cur) return nullptr;//node为空,直接返回
//cur = cur->rightChild;//cur指向node的右子树的父节点
while (cur->leftChild)
cur = cur->leftChild;
return cur;
}
/******************删除节点************************/
template <typename Type>
void Bst<Type>::Delete(const Element<Type>& _data)
{
BstNode<Type> *deleteNode = nullptr;
BstNode<Type> *deleteNodeParent = nullptr;
BstNode<Type> *minNode = nullptr;
BstNode<Type> *maxNode = nullptr;
deleteNode = Search(_data);
if (!deleteNode) return;//deleteNode为空,表明BST中没有元素为_data的节点,直接返回
if (deleteNode->leftChild){//deleteNode有左子树,得到deleteNode左子树的最大值节点
maxNode = FindMax(deleteNode->leftChild);
}
if (deleteNode->rightChild){//deleteNode有右子树,得到deleteNode右子树的最小值节点
minNode = FindMin(deleteNode->rightChild);
}
deleteNodeParent = FindParent(deleteNode);//找到deleteNode节点的父节点
//maxNode和minNode的节点为空,表明deleteNode是一个叶子节点
if (!maxNode && !minNode){
if (deleteNodeParent->leftChild == deleteNode)
deleteNodeParent->leftChild = nullptr;
else
deleteNodeParent->rightChild = nullptr;
delete deleteNode;
}
//表明deleteNode最少有一个子树不空
else{
//1.将tmp节点的父节点和tmp的子节点连接
BstNode<Type> *tmp = (maxNode == nullptr) ? minNode : maxNode;
BstNode<Type> * tmpParent = FindParent(tmp);
if (tmp->leftChild){//左孩子不空,右孩子必空.此情况对应的是 maxNode
if (tmpParent->leftChild == tmp)//tmp是左孩子
tmpParent->leftChild = tmp->leftChild;
else
tmpParent->rightChild = tmp->leftChild;
}
else{//右孩不空,左孩子必空,此情况对应的是 minNode
if (tmpParent->leftChild == tmp)
tmpParent->leftChild = tmp->rightChild;
else
tmpParent->rightChild = tmp->rightChild;
}
//2.将tmp节点和deleteNode的父节点连接
if (deleteNodeParent == nullptr)
root = tmp;
else{
if (tmp->content.key < deleteNodeParent->content.key)
deleteNodeParent->leftChild = tmp;
else
deleteNodeParent->rightChild = tmp;
}
//3.将tmp节点的左右孩子连接上deleteNode的左右孩子
tmp->leftChild = deleteNode->leftChild;
tmp->rightChild = deleteNode->rightChild;
delete deleteNode;
}
}
/******************中序遍历InOrder************************/
template <typename Type>
void Bst<Type>::InOrder()
{
InOrder(root);
}
template <typename Type>
void Bst<Type>::InOrder(BstNode<Type>* node)
{
if (node == nullptr)
return;
InOrder(node->leftChild);
std::cout << node->content.key << std::endl;
InOrder(node->rightChild);
}
/******************层序遍历InOrder************************/
template <typename Type>
void Bst<Type>::LevelOrder()
{
LevelOrder(root);
}
template <typename Type>
void Bst<Type>::LevelOrder(BstNode<Type>* node)
{
queue<BstNode<Type>*> q;
q.push(node);
while (!q.empty()){
int size = q.size();
std::cout << "[";
for (int i = 0; i < size; i++){
BstNode<Type>* tmp = q.front();
q.pop();
std::cout << tmp->content.key << " ";
if (tmp->leftChild) q.push(tmp->leftChild);
if (tmp->rightChild) q.push(tmp->rightChild);
}
std::cout <<"]" <<std::endl;
}
}
/******************查找结点的父节点FindParent************************/
template <typename Type>
BstNode<Type>* Bst<Type>::FindParent(BstNode<Type>* node)
{
//node = root.表明node无父节点
if (root == node)
return nullptr;
BstNode<Type>* cur = root;
while (cur && root){
//返回父节点
if (cur->leftChild == node || cur->rightChild == node)
return cur;
//cur节点不是node的父节点,根据key确定从cur的左子树找还是右子树找
if (node->content.key < cur->content.key)
cur = cur->leftChild;
else
cur = cur->rightChild;
}
return nullptr;
}
#endif
main.cpp如下:
#include
#include "Bst.h"
using namespace std;
int main()
{
Bst<int> tree;
Element<int> e1(5);
Element<int> e2(4);
Element<int> e3(3);
Element<int> e4(9);
Element<int> e5(1);
Element<int> e6(7);
/*
5
4 9
3 7
1
*/
tree.Insert(e1);
tree.Insert(e2);
tree.Insert(e3);
tree.Insert(e4);
tree.Insert(e5);
tree.Insert(e6);
cout << "原树的中序遍历和层序遍历:" << endl;
tree.InOrder();
tree.LevelOrder();
cout << "删除节点e2的中序遍历和层序遍历:" << endl;
tree.Delete(e2);
tree.InOrder();
tree.LevelOrder();
cout << "删除节点e1的中序遍历和层序遍历:" << endl;
tree.Delete(e1);
tree.InOrder();
tree.LevelOrder();
system("pause");
return 0;
}