二叉搜索树
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树

注:
- 二叉搜索树查找一个值最多查找高度次
- 二叉搜索树按中序遍历,值可以从小到大打印出来
二叉搜索树操作
二叉搜索树的插入
- 根节点为空,直接插入
- 根节点不为空:
-
- 如果该节点key==要插入的key ,返回false
-
- 如果该节点key>要插入的key ,则向该节点的左子树查找(若该节点的左子树为空,则直接插入)
-
- 如果该节点key
<要插入的key ,则向该节点的右子树查找(若该节点的右子树为空,则直接插入)<="" li="">
要插入的key>
- 如果该节点key
二叉搜索树的查找

- 如果根节点key==查找key,返回true
- 如果根节点key>查找key,在其左子树查找
- 如果根节点key
<查找key,在其右子树查找
否则返回false
查找key,在其右子树查找
若根节点为空,返回false
二叉搜索树的删除
二叉搜索树的实现(递归及非递归)
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include
using namespace std; template<class K> struct BSTreeNode {
BSTreeNode(const K& key) :_left(nullptr) ,_right(nullptr) ,_key(key) {
} BSTreeNode<K>* _left; BSTreeNode<K>* _right; K _key; }; template<class K> class BSTree {
typedef BSTreeNode<K> Node; public: // BSTree() = default; 强制编译器自动生成默认构造函数 BSTree() :_root(nullptr) {
} //也可写成 BSTree(const BSTree& t) BSTree(const BSTree<K>& t) {
_root = _Copy(t._root); } //BSTree
& operator=(BSTree t)
BSTree<K>& operator=(BSTree<K> t) {
swap(_root, t._root); return *this; } ~BSTree() {
_Destroy(_root); } bool Insert(const K& key) {
if (_root == nullptr) {
_root = new Node(key); return true; } //找出要插入的位置 Node* parent = nullptr; Node* cur = _root; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
return false; } } cur = new Node(key); if (parent->_key > key) {
parent->_left = cur; } else {
parent->_right = cur; } return true; } void InOrder() {
_InOrder(_root); cout << endl; } Node* Find(const K& key) {
Node* cur = _root; while (cur) {
if (cur->_key > key) {
cur = cur->_left; } else if (cur->_key < key) {
cur = cur->_right; } else {
return cur; } } return nullptr; } bool Erase(const K& key) {
Node* cur = _root; Node* parent = nullptr; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
if (cur->_left == nullptr) {
if (cur == _root) {
_root = cur->_right; } else {
if (parent->_left == cur) {
parent->_left = cur->_right; } else {
parent->_right = cur->_right; } } delete cur; } else if (cur->_right == nullptr) {
if (cur == _root) {
_root = cur->_left; } else {
if (parent->_left == cur) {
parent->_left = cur->_left; } else {
parent->_right = cur->_left; } } delete cur; } else {
//找右树最小节点去替代删除 Node* minrightparent = cur; Node* minright = cur->_right; while (minright->_left) {
minrightparent = minright; minright = minright->_left; } cur->_key = minright->_key; if (minrightparent->_left == minright) {
minrightparent->_left = minright->_right; } else {
minrightparent->_right = minright->_right; } delete minright; } return true; } } return false; } //递归版本 bool InsertR(const K& key) {
return _InsertR(_root, key); } Node* FindR(const K& key) {
return _FindR(_root, key); } bool EraseR(const K& key) {
return _EraseR(_root, key); } private: Node* _Copy(Node* root) {
if (root == nullptr) return nullptr; Node* newnode = new Node(root->_key); newnode->_left = _Copy(root->_left); newnode->_right = _Copy(root->_right); return newnode; } void _Destroy(Node* root) {
if (root == nullptr) {
return; } _Destroy(root->_left); _Destroy(root->_right); delete root; } bool _EraseR(Node*& root, const K& key) {
if (root == nullptr) {
return false; } else {
if (root->_key > key) {
return _EraseR(root->_left, key); } else if (root->_key < key) {
return _EraseR(root->_right, key); } else {
Node* del = root; if (root->_left == nullptr) {
root = root->_right; } else if (root->_right == nullptr) {
root = root->_left; } else {
//替代法删除 Node* minright = root->_right; while (minright->_left) {
minright = minright->_left; } root->_key = minright->_key; //转换成递归在右子树中删除最小节点 return _EraseR(root->_right, minright->_key); //注意:转换在递归删除右子树中minright如果右子树越大 //付出的代价就越大相当于重新查找了一遍 } delete del; return true; } } } Node* _FindR(Node* root, const K& key) {
if (root == nullptr) {
return nullptr; } else {
if (root->_key > key) {
return _FindR(root->_left, key); } else if (root->_key < key) {
return _FindR(root->_right, key); } else {
return root; } } } bool _InsertR(Node*& root, const K& key) {
if (root == nullptr) {
root = new Node(key); return true; } else {
if (root->_key > key) {
return _InsertR(root->_left, key); } else if (root->_key < key) {
return _InsertR(root->_right, key); } else {
return false; } } } void _InOrder(Node* root) {
if (root == nullptr) {
return; } _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); } Node* _root=nullptr; };
注:尽量使用循环来写,不要用递归。因为递归一方面每次调用函数都要建立栈帧,另一方面递归深度太深会导致栈溢出
二叉搜索树的应用
- K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
- 以单词集合中的每个单词作为key,构建一棵二叉搜索树
- 在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
- KV模型:每一个关键码key,都有与之对应的值Value,即
的键值对。该种方式在现实生活中非常常见:比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文
就构成一种键值对;再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是
就构成一种键值对。比如:实现一个简单的英汉词典dict,可以通过英文找到与其对应的中文,具体实现方式如下:
-
<单词,中文含义>
为键值对构造二叉搜索树,注意:二叉搜索树需要比较,键值对比较时只比较Key
单词,中文含义> - 查询英文单词时,只需给出英文单词,就可快速找到与其对应的key
K模型:
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include
using namespace std; //确定一个只是不是在集合中 namespace KEY {
template<class K> struct BSTreeNode {
BSTreeNode(const K& key) :_left(nullptr) , _right(nullptr) , _key(key) {
} BSTreeNode<K>* _left; BSTreeNode<K>* _right; K _key; }; template<class K> class BSTree {
typedef BSTreeNode<K> Node; public: // BSTree() = default; 强制编译器自动生成默认构造函数 BSTree() :_root(nullptr) {
} //也可写成 BSTree(const BSTree& t) BSTree(const BSTree<K>& t) {
_root = _Copy(t._root); } //BSTree
& operator=(BSTree t)
BSTree<K>& operator=(BSTree<K> t) {
swap(_root, t._root); return *this; } ~BSTree() {
_Destroy(_root); } bool Insert(const K& key) {
if (_root == nullptr) {
_root = new Node(key); return true; } //找出要插入的位置 Node* parent = nullptr; Node* cur = _root; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
return false; } } cur = new Node(key); if (parent->_key > key) {
parent->_left = cur; } else {
parent->_right = cur; } return true; } void InOrder() {
_InOrder(_root); cout << endl; } Node* Find(const K& key) {
Node* cur = _root; while (cur) {
if (cur->_key > key) {
cur = cur->_left; } else if (cur->_key < key) {
cur = cur->_right; } else {
return cur; } } return nullptr; } bool Erase(const K& key) {
Node* cur = _root; Node* parent = nullptr; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
if (cur->_left == nullptr) {
if (cur == _root) {
_root = cur->_right; } else {
if (parent->_left == cur) {
parent->_left = cur->_right; } else {
parent->_right = cur->_right; } } delete cur; } else if (cur->_right == nullptr) {
if (cur == _root) {
_root = cur->_left; } else {
if (parent->_left == cur) {
parent->_left = cur->_left; } else {
parent->_right = cur->_left; } } delete cur; } else {
//找右树最小节点去替代删除 Node* minrightparent = cur; Node* minright = cur->_right; while (minright->_left) {
minrightparent = minright; minright = minright->_left; } cur->_key = minright->_key; if (minrightparent->_left == minright) {
minrightparent->_left = minright->_right; } else {
minrightparent->_right = minright->_right; } delete minright; } return true; } } return false; } private: Node* _Copy(Node* root) {
if (root == nullptr) return nullptr; Node* newnode = new Node(root->_key); newnode->_left = _Copy(root->_left); newnode->_right = _Copy(root->_right); return newnode; } void _Destroy(Node* root) {
if (root == nullptr) {
return; } _Destroy(root->_left); _Destroy(root->_right); delete root; } void _InOrder(Node* root) {
if (root == nullptr) {
return; } _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); } Node* _root = nullptr; }; }
KV模型:
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include
using namespace std; namespace KEY_VALUE {
template<class K, class V> struct BSTreeNode {
BSTreeNode(const K& key, const V& value) :_left(nullptr) , _right(nullptr) , _key(key) , _value(value) {
} BSTreeNode<K,V>* _left; BSTreeNode<K,V>* _right; K _key; V _value; }; template<class K, class V> class BSTree {
typedef BSTreeNode<K, V> Node; public: // BSTree() = default; 强制编译器自动生成默认构造函数 BSTree() :_root(nullptr) {
} BSTree(const BSTree<K, V>& t) {
_root = _Copy(t._root); } BSTree<K,V>& operator=(BSTree<K, V> t) {
swap(_root, t._root); return *this; } ~BSTree() {
_Destroy(_root); } bool Insert(const K& key, const V& value) {
if (_root == nullptr) {
_root = new Node(key, value); return true; } //找出要插入的位置 Node* parent = nullptr; Node* cur = _root; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
return false; } } cur = new Node(key, value); if (parent->_key > key) {
parent->_left = cur; } else {
parent->_right = cur; } return true; } void InOrder() {
_InOrder(_root); cout << endl; } Node* Find(const K& key) {
Node* cur = _root; while (cur) {
if (cur->_key > key) {
cur = cur->_left; } else if (cur->_key < key) {
cur = cur->_right; } else {
return cur; } } return nullptr; } bool Erase(const K& key) {
Node* cur = _root; Node* parent = nullptr; while (cur) {
if (cur->_key > key) {
parent = cur; cur = cur->_left; } else if (cur->_key < key) {
parent = cur; cur = cur->_right; } else {
if (cur->_left == nullptr) {
if (cur == _root) {
_root = cur->_right; } else {
if (parent->_left == cur) {
parent->_left = cur->_right; } else {
parent->_right = cur->_right; } } delete cur; } else if (cur->_right == nullptr) {
if (cur == _root) {
_root = cur->_left; } else {
if (parent->_left == cur) {
parent->_left = cur->_left; } else {
parent->_right = cur->_left; } } delete cur; } else {
//找右树最小节点去替代删除 Node* minrightparent = cur; Node* minright = cur->_right; while (minright->_left) {
minrightparent = minright; minright = minright->_left; } cur->_key = minright->_key; if (minrightparent->_left == minright) {
minrightparent->_left = minright->_right; } else {
minrightparent->_right = minright->_right; } delete minright; } return true; } } return false; } private: Node* _Copy(Node* root) {
if (root == nullptr) return nullptr; Node* newnode = new Node(root->_key, root->_value); newnode->_left = _Copy(root->_left); newnode->_right = _Copy(root->_right); return newnode; } void _Destroy(Node* root) {
if (root == nullptr) {
return; } _Destroy(root->_left); _Destroy(root->_right); delete root; } void _InOrder(Node* root) {
if (root == nullptr) {
return; } _InOrder(root->_left); cout << root->_key << ":" << root->_value << endl; _InOrder(root->_right); } Node* _root = nullptr; }; }
二叉搜索树的性能分析
- 插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
- 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
- 但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树查找次数是logN;最差情况下,二叉搜索树查找次数是N
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/213712.html原文链接:https://javaforall.net
