二叉查找树

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

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值