二叉查找树

来源:互联网 发布:数据分析报告 编辑:程序博客网 时间:2024/06/05 04:25

二叉查找树是一种特殊的二叉树,除了拥有普通二叉树的性质之后,这种数据结构最重要的特征是:对于任何一个结点,它的值都大于或等于它的左子树上所有结点的值,而小于它的右子树上所有结点的值。这种数据结构有较高的查找效率和插入效率,同时为了方便各种操作,还在每个结点中引入一个指针域,用于指向结点的父亲。

二叉查找树一般的操作包括以下几种:

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;}