二叉查找树是一种特殊的二叉树,除了拥有普通二叉树的性质之后,这种数据结构最重要的特征是:对于任何一个结点,它的值都大于或等于它的左子树上所有结点的值,而小于它的右子树上所有结点的值。这种数据结构有较高的查找效率和插入效率,同时为了方便各种操作,还在每个结点中引入一个指针域,用于指向结点的父亲。
二叉查找树一般的操作包括以下几种:
1、查找是否存在某个结点,其值等于给定值
对于查找操作,只需要从根结点开始,对比给定值于当前结点的值的大小,若相等,则返回当前结点;若给定值小于当前结点的值,则往当前结点的左子树中查找;否则往当前结点的右子树中查找。
2、插入一个新结点
对于插入操作,需要先找到在哪个位置进行插入操作,因此类似于查找操作,先从上到下找到最后一个非空结点。然后判断新结点的值与该结点的值的大小关系,若新结点的值比较小或两者相等,则将新结点作为该结点的左孩子,否则作为右孩子。
3、删除某个结点
删除某个结点需要进行一些判断。首先是判断要删除的结点是不是根结点,其次是判断要删除的结点的孩子状况。
主要包括以下几种情况:
(1)根结点,无孩子:直接删除,将根结点置空即可
(2)根结点,有左孩子:将左孩子作为新的根结点,删除当前结点
(3)根结点,有右孩子:将右孩子作为新的根结点,删除当前结点
(4)根结点,有两个孩子:先获取左子树中值最大的结点,将它作为新的根结点,当前根结点的右子树作为新的根结点的右子树,删除当前根结点
(5)非根结点,无孩子:直接删除,将父亲结点的相应指针置空即可
(6)非根结点,有左孩子:将父亲结点的相应指针指向当前结点的左孩子,删除当前结点
(7)非根结点,有右孩子:将父亲结点的相应指针指向当前结点的右孩子,删除当前结点
(8)非根结点,有两个孩子:找到左子树中值最大的结点,将当前结点的值修改为该最大值,删除刚刚找到的左子树中值最大的结点,再修改相应的指针
4、遍历树中的所有结点(先序、中序、后序)
这个类似于二叉树的遍历,用递归即可。
5、获取以某个结点为根的树上的结点值最大和最小的结点
从当前结点一直往左走到尽头,即可获得最小值。同理,从当前结点一直往右走到尽头,即可获得最大值。
6、(非常用操作)获取在先序遍历中,某个结点的前缀和后缀
详细代码如下:
//BinarySearchTree.h
#ifndef _BINARY_SEARCH_TREE_
#define _BINARY_SEARCH_TREE_
#include <iostream>
class TreeNode
{
public:
TreeNode* parent; //结点的父亲
TreeNode* lchild; //结点的左孩子
TreeNode* rchild; //结点的右孩子
int val; //结点的值
TreeNode(int _val);
~TreeNode();
};
class BinarySearchTree
{
public:
BinarySearchTree(TreeNode* _root = NULL);
~BinarySearchTree();
TreeNode* getRoot(); //返回根结点
TreeNode* getMinimum(TreeNode* _root); //返回值最大的结点
TreeNode* getMaximum(TreeNode* _root); //返回值最小的结点
TreeNode* searchValue(int _val); //查找值等于某个数的结点
TreeNode* getSuccessor(TreeNode* _treeNode); //返回中序遍历时,某个结点的后缀
TreeNode* getPredecessor(TreeNode* _treeNode); //返回中序遍历时,某个结点的前缀
void insertNode(TreeNode* _treeNode); //插入结点
void deleteNode(TreeNode* _treeNode); //删除结点
void inOrderTraverse(TreeNode* root); //中序遍历
void preOrderTraverse(TreeNode* root); //先序遍历
void postOrderTraverse(TreeNode* root); //后序遍历
protected:
private:
TreeNode* root; //二叉树的根
void deleteTree(TreeNode* _root); //删除二叉树中的结点,用于清理空间
};
#endif
//BinarySearchTree.cpp
#include "BinarySearchTree.h"
using namespace std;
TreeNode::TreeNode(int _val): parent(NULL), lchild(NULL), rchild(NULL), val(_val)
{
}
TreeNode::~TreeNode()
{
}
BinarySearchTree::BinarySearchTree(TreeNode* _root): root(_root)
{
}
BinarySearchTree::~BinarySearchTree()
{
deleteTree(root);
}
TreeNode* BinarySearchTree::getRoot()
{
return root;
}
TreeNode* BinarySearchTree::getMinimum(TreeNode* _root)
{
if (_root == NULL) return NULL;
TreeNode* temp = _root;
while (temp->lchild)
{
temp = temp->lchild;
}
return temp;
}
TreeNode* BinarySearchTree::getMaximum(TreeNode* _root)
{
if (_root == NULL) return NULL;
TreeNode* temp = _root;
while (temp->rchild)
{
temp = temp->rchild;
}
return temp;
}
TreeNode* BinarySearchTree::searchValue(int _val)
{
TreeNode* temp = root;
while (temp != NULL && temp->val != _val)
{
if (temp->val > _val) temp = temp->lchild;
else temp = temp->rchild;
}
return temp;
}
TreeNode* BinarySearchTree::getSuccessor(TreeNode* _treeNode)
{
TreeNode* temp = _treeNode;
if (temp->rchild) return getMinimum(temp->rchild);
TreeNode* p = temp->parent;
while (p && p->rchild == temp)
{
temp = p;
p = p->parent;
}
return p;
}
TreeNode* BinarySearchTree::getPredecessor(TreeNode* _treeNode)
{
TreeNode* temp = _treeNode;
if (temp->lchild) return getMaximum(temp->lchild);
TreeNode* p = temp->parent;
while (p && p->lchild == temp)
{
temp = p;
p = p->parent;
}
return p;
}
void BinarySearchTree::insertNode(TreeNode* _treeNode)
{
TreeNode* p = root;
TreeNode* temp = NULL;
while (p)
{
temp = p;
if (p->val >= _treeNode->val) p = p->lchild;
else p = p->rchild;
}
if (!temp) root = _treeNode;
else if (temp->val >= _treeNode->val)
{
temp->lchild = _treeNode;
_treeNode->parent = temp;
}
else
{
temp->rchild = _treeNode;
_treeNode->parent = temp;
}
}
void BinarySearchTree::deleteNode(TreeNode* _treeNode)
{
if (_treeNode->lchild && _treeNode->rchild)
{
TreeNode* maxNode = getMaximum(_treeNode->lchild);
if (maxNode->parent == _treeNode)
{
maxNode->rchild = _treeNode->rchild;
maxNode->parent = NULL;
delete _treeNode;
root = maxNode;
}
else
{
maxNode->parent->rchild = maxNode->lchild;
if (maxNode->lchild) maxNode->lchild->parent = maxNode->parent;
_treeNode->val = maxNode->val;
delete maxNode;
}
}
else if (_treeNode->lchild)
{
if (_treeNode->parent == NULL)
{
root = _treeNode->lchild;
root->parent = NULL;
delete _treeNode;
}
else
{
TreeNode* p = _treeNode->parent;
if (p->lchild == _treeNode) p->lchild = _treeNode->lchild;
else p->rchild = _treeNode->lchild;
_treeNode->lchild->parent = p;
delete _treeNode;
}
}
else if (_treeNode->rchild)
{
if (_treeNode->parent == NULL)
{
root = _treeNode->rchild;
root->parent = NULL;
delete _treeNode;
}
else
{
TreeNode* p = _treeNode->parent;
if (p->lchild == _treeNode) p->lchild = _treeNode->rchild;
else p->rchild = _treeNode->rchild;
_treeNode->rchild->parent = p;
delete _treeNode;
}
}
else
{
if (_treeNode->parent == NULL)
{
delete _treeNode;
root = NULL;
}
else
{
TreeNode* p = _treeNode->parent;
if (p->lchild == _treeNode) p->lchild = NULL;
else p->rchild = NULL;
delete _treeNode;
}
}
}
void BinarySearchTree::deleteTree(TreeNode* _root)
{
if (!_root) return;
if (_root->lchild) deleteTree(_root->lchild);
if (_root->rchild) deleteTree(_root->rchild);
delete _root;
}
void BinarySearchTree::inOrderTraverse(TreeNode* _root)
{
if (!_root) return;
if (_root->lchild) inOrderTraverse(_root->lchild);
cout << _root->val << endl;
if (_root->rchild) inOrderTraverse(_root->rchild);
}
void BinarySearchTree::preOrderTraverse(TreeNode* _root)
{
if (!_root) return;
cout << _root->val << endl;
if (_root->lchild) preOrderTraverse(_root->lchild);
if (_root->rchild) preOrderTraverse(_root->rchild);
}
void BinarySearchTree::postOrderTraverse(TreeNode* _root)
{
if (!_root) return;
if (_root->lchild) postOrderTraverse(_root->lchild);
if (_root->rchild) postOrderTraverse(_root->rchild);
cout << _root->val << endl;
}
//main.cpp
#include "BinarySearchTree.h"
#include <string>
using namespace std;
int main()
{
string str;
int val;
TreeNode* node;
BinarySearchTree bst;
while (cin >> str)
{
if (str == "SEARCH" || str == "search")
{
cin >> val;
node = bst.searchValue(val);
if (node) cout << "find " << val << " successfully!" << endl;
else cout << "can't find " << val << endl;
}
else if (str == "INSERT" || str == "insert")
{
cin >> val;
bst.insertNode(new TreeNode(val));
}
else if (str == "DELETE" || str == "delete")
{
cin >> val;
node = bst.searchValue(val);
if (node) bst.deleteNode(node);
}
else if (str == "MAX" || str == "max")
{
node = bst.getRoot();
if (node) cout << bst.getMaximum(node)->val << endl;
else cout << "the tree is empty" << endl;
}
else if (str == "MIN" || str == "min")
{
node = bst.getRoot();
if (node) cout << bst.getMinimum(node)->val << endl;
else cout << "the tree is empty" << endl;
}
else if (str == "INORDER" || str == "inorder")
{
node = bst.getRoot();
bst.inOrderTraverse(node);
}
else if (str == "PREORDER" || str == "preorder")
{
node = bst.getRoot();
bst.preOrderTraverse(node);
}
else if (str == "POSTORDER" ||str == "postorder")
{
node = bst.getRoot();
bst.postOrderTraverse(node);
}
else if (str == "SUCCESSOR" || str == "successor")
{
cin >> val;
node = bst.searchValue(val);
if (!node) cout << "can't find " << val << endl;
else
{
node = bst.getSuccessor(node);
if (!node) cout << "no successor for " << val << endl;
else cout << node->val << endl;
}
}
else if (str == "PREDECESSOR" || str == "predecessor")
{
cin >> val;
node = bst.searchValue(val);
if (!node) cout << "can't find " << val << endl;
else
{
node = bst.getPredecessor(node);
if (!node) cout << "no predecessor for " << val << endl;
else cout << node->val << endl;
}
}
else break;
}
return 0;
}