目录
一, 二叉搜索树的特性
二, 二叉搜索树的实现
三,二叉树搜索树的应用分析
1,K模型
2, KV模型
3,性能分析
四,二叉树的OJ题目
1. 二叉树创建字符串。
2. 二叉树的分层遍历1。
3. 二叉树的分层遍历2。
4. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先 。
5. 二叉树搜索树转换成排序双向链表。
6. 根据一棵树的前序遍历与中序遍历构造二叉树。
7. 根据一棵树的中序遍历与后序遍历构造二叉树。
8. 二叉树的前序遍历,非递归迭代实现 。
9. 二叉树中序遍历 ,非递归迭代实现。
10. 二叉树的后序遍历 ,非递归迭代实现。
“二叉搜索树”又称“二叉排序树”,它可以为空;
如果不为空,则满足一下性质:
1,若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2,若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3,左、右子树都是二叉搜索树
#pragma once
#include
template
struct BSTreeNode
{
BSTreeNode* _left;
BSTreeNode* _right;
K _key;
BSTreeNode (const K& key)
:_left(nullptr)
,_right(nullptr)
,_key(key)
{}
};
template
class BSTree
{
typedef BSTreeNode Node;
public:
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (key > parent->_key)
{
parent->_right = cur;
}
else if (key < parent->_key)
{
parent->_left = cur;
}
return true;
}
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else if (key == cur->_key)
{
return true;
}
}
return false;
}
bool Erase (const K& key)
{
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
//先找到key节点,判断是否存在,再进行删除
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else // 开始删除节点
{
// 要删除的节点可分4种情况,其中左右都为空的情况,可归并到前2种
// 1, 左为空,右有节点(继承法)
// 2, 右为空,左有节点(继承法)
// 3, 左右都有节点(用替换法删除,替换左子树最大或者右子树最小)
// (假设是右子树最小,则为无字节点或者右边有节点)
// 4,如果删除节点为根节点,需要单独判断
if (cur->_left == nullptr) // 继承法删除
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
delete cur;
cur == nullptr;
}
else if (cur->_right == nullptr) // 继承法删除
{
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
cur == nullptr;
}
else // 用替换法删除cur
{
// 找右子树最小节点rightmin进行替换
Node* minparent = cur;
Node* rightmin = cur->_right;
// 找节点rightmin
while (rightmin->_left)
{
minparent = rightmin;
rightmin = rightmin->_left;
}
// 互换数值
swap(cur->_key, rightmin->_key);
// 重新链接节点!!! 易错重点!!!
if (minparent->_left == rightmin)
{
minparent->_left = rightmin->_right;
}
else
{
minparent->_right = rightmin->_right;
}
// 删除节点
delete rightmin;
}
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
// C++11的用法:强制编译器生成默认构造
BSTree() = default;
~BSTree()
{
_Destory(_root);
}
BSTree(const BSTree& t)
{
_root = _Copy(t._root);
}
// t2 = t1 ,拷贝构造,直接使用传值传参
BSTree& operator=(BSTree t)
{
swap(_root, t._root);
return *this;
}
private:
void _Destory(Node*& root)
{
if (root == nullptr)
{
return;
}
_Destory(root->_left);
_Destory(root->_right);
delete root;
root = nullptr;
}
Node* _Copy(Node* root)
{
if (root == nullptr)
{
return nullptr;
}
Node* copyRoot = new Node(root->_key);
copyRoot->_left = _Copy(root->_left);
copyRoot->_right = _Copy(root->_right);
return copyRoot;
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
bool _FindR(Node* root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (key > root->_key)
{
return _FindR(root->_right, key);
}
else if (key < root->_key)
{
return _FindR(root->_left, key);
}
return true;
}
//注意使用Node的指针的引用
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (key > root->_key)
{
return _InsertR(root->_right, key);
}
else if (root->_key > key)
{
return _InsertR(root->_left, key);
}
else
{
return false;
}
}
bool _EraseR(Node*& root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (key > root->_key)
{
return _EraseR(root->_right, key);
}
else if (key < root->_key)
{
return _EraseR(root->_left, key);
}
else
{
Node* del = root;
if (root->_left == nullptr)
{
root = root->_right;
}
else if(root->_right == nullptr)
{
root = root->_left;
}
else
{
// 找右子树的最左节点min进行替换
Node* min = root->_right;
while (min->_left)
{
min = min->_left;
}
// 替换
swap(root->_key, min->_key);
// 替换之后,顺序变化,再从根开始找,找不到key,所以要把根换成右子树
return _EraseR(root->_right, key);
}
delete del;
return true;
}
}
private:
Node* _root = nullptr;
};
void test1()
{
BSTree t;
int a[] = { 8,3,1,10,6,4,7,14,13 };
for (auto e : a)
{
t.Insert(e);
}
t.InOrder();
BSTree r;
int b[] = { 8,3,1,10,6,4,7,14,13,4,3,4 };
for (auto e : b)
{
// 用插入法创建二叉树,自带排序和去重, 两次输出结果相同,3和4去重后只剩1个
r.Insert(e);
}
r.InOrder();
bool c = t.Find(5);
cout << c << endl;
bool d = t.Find(10);
cout << d << endl;
r.Erase(3);
r.InOrder();
r.Erase(8);
r.InOrder();
for (auto e : b)
{
r.Erase(e);
r.InOrder();
}
r.InOrder();
}
void test2()
{
BSTree t;
int a[] = { 8,3,1,10,6,4,7,14,13 };
for (auto e : a)
{
t.Insert(e);
}
bool b = t.FindR(5);
cout << b << endl;
bool c = t.FindR(10);
cout << c << endl;
t.EraseR(8);
t.InOrder();
t.InsertR(99);
t.InOrder();
t.EraseR(14);
t.InOrder();
t.InsertR(-45);
t.InOrder();
}
void test3()
{
BSTree t;
int a[] = { 8,3,1,10,6,4,7,14,13 };
for (auto e : a)
{
t.Insert(e);
}
BSTree copy = t;
copy.InOrder();
t.InOrder();
BSTree t1;
t.Insert(2);
t.Insert(1);
t.Insert(3);
copy = t1;
copy.InOrder();
t1.InOrder();
}
K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。
比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
1)以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树
2)在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。