特点:
二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree)
一般具有下面的特点:
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
任意节点的左、右子树也分别为二叉查找树。
没有键值相等的节点(no duplicate nodes)。
分析如何删除搜索二叉树中的一个节点
①、左子树为空
使该节点的父节点左节点(右节点)指向该节点的右子树
②、右子树为空
使该节点的父节点的左节点(右节点)指向该节点的左子树
③。左右子树都不为空—->替换法删除
第一种方法:找到该节点的右子树中的最左节点(是右子树中最小的节点)和要删除的节点的键值进行替换。
第二种方法:找到该节点的左子树中的最右节点(是左子树中的最大的一个节点)和要删除的节点的键值进行替换。
代码如下:
(递归和非递归)
非递归图解:
递归删除图解:
BinarySearchTree.hpp
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;
template<class K>
struct BinarySearchTreeNode
{
BinarySearchTreeNode()
:_left(NULL)
, _right(NULL)
{}
BinarySearchTreeNode(const K& key)
:_key(key)
, _left(NULL)
, _right(NULL)
{}
BinarySearchTreeNode<K>* _left;
BinarySearchTreeNode<K>* _right;
K _key;
};
template<class K>
class BinarySearchTree
{
typedef BinarySearchTreeNode<K> Node;
public:
BinarySearchTree()
:_root(NULL)
{}
BinarySearchTree(Node* node)
:_root(node)
{}
//递归查找
Node* FindR(const K& key)
{
return _FindR(_root, key);
}
//递归插入
bool InsertR(const K& key)
{
return _InsertR(, _root, key);
}
bool Insert(const K& key)
{
if (NULL == _root)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = NULL;
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是parent的左孩子还是右孩子
if (key > parent->_key)
{
parent->_right = new Node(key);
}
else
{
parent->_left = new Node(key);
}
return true;
}
const 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 NULL;
}
bool Remove(const K& key)
{
Node* cur = _root;
Node* parent = NULL;
Node* del = NULL;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
//1.cur的左为空
if (NULL == cur->_left)
{
del = cur;
if (NULL == parent)//当此时的cur为根节点
{
_root = cur->_right;
}
else if (parent->_left == cur)//cur为parent的左孩子
{
parent->_left = cur->_right;
}
else //cur为parent的右孩子
{
parent->_right = cur->_right;
}
}//2.cur的右为空
else if (NULL == cur->_right)
{
del = cur;
if (NULL == parent)
{
_root = cur->_left;
}
else if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}//3.cur的左右都不为空(替换法删除)
else
{
//①找右子树的最左节点并删除
Node* subRight = cur->_right;
Node* parent = cur;//注意这里的parent不能是NULL(如果右子树的最左节点是根节点循环进去)
while (subRight->_left)
{
parent = subRight;
subRight = subRight->_left;
}
del = subRight;//需要删除的节点
cur->_key = subRight->_key;
//还需判断subRight是parent的左节点还是右节点
if (parent->_left == subRight)
{
parent->_left = subRight->_right;
}
else
{
parent->_right = subRight->_right;
}
}
delete del;
return true;
}
}
return false;
}
bool RemoveR(const K& key)
{
return _RemoveR(_root, key);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
~BinarySearchTree()
{
_destory(_root);
}
private:
bool _RemoveR(Node*& root, const K& key)
{
if (NULL == root)
{
return false;
}
if (root->_key < key)
{
return _RemoveR(root->_right, key);
}
else if (root->_key > key)
{
return _RemoveR(root->_left, key);
}
else
{
Node* del = root;
//1.root的左节点为空
if (NULL == root->_left)
{
root = root->_right;
delete del;
}//2.root的右节点为空
else if (NULL == root->_right)
{
root = root->_left;
delete del;
}
else
{
//3.root的左右节点都不为空
Node* left = root->_right;
//方法①:
//Node* parent = root;
//while (left->_left)
//{
// parent = left;
// left = left->_left;
//}
//del = left;
//root->_key = left->_key;//替换法删除
//
//if (left == parent->_left)
//{
// parent->_left = left->_right;
//}
//else
//{
// parent->_right = left->_right;
//}
//delete del;
//方法②:
while (left->_left)
{
left = left->_left;
}
root->_key = left->_key;
_RemoveR(root->_right, left->_key);
}
}
}
bool _InsertR(Node*& root, const K& key)
{
if (NULL == root)
{
root = new Node(key);
return true;
}
if (root->_key > key)
{
return _Insert(root->_left, key);
}
else if (root->_key < key)
{
return _Insert(root->_right, key);
}
else
{
return false;
}
}
Node* _FindR(Node* root, const K& key)
{
if (NULL == root)
{
return NULL;
}
if (root->_key > key)
{
return _FindR(root->_left, key);
}
else if (root->_key < key)
{
return _FindR(root->_right, key);
}
else
{
return root;
}
}
void _destory(Node* root)
{
if (NULL == root)
{
return;
}
_destory(root->_left);
_destory(root->_right);
delete root;
}
void _InOrder(Node* root)
{
if (NULL == root)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
Node* _root;
};
测试代码:
#include"BinarySearchTree1.h"
void Test()
{
int array[] = {5,3,4,1,7,8,2,6,0,9,};
BinarySearchTree<int> tree;
for (size_t index = 0; index < sizeof(array) / sizeof(int); ++index)
{
tree.Insert(array[index]);
}
tree.InOrder();
if (tree.Find(7))
{
cout << tree.Find(7)->_key << endl;
}
tree.Remove(3);
tree.Remove(5);
tree.Remove(4);
tree.InOrder();
tree.Remove(1);
tree.Remove(7);
tree.Remove(8);
tree.Remove(2);
tree.InOrder();
tree.Remove(0);
tree.Remove(6);
tree.InOrder();
tree.Remove(9);
tree.InOrder();
tree.Remove(3);
tree.InOrder();
tree.Remove(5);
tree.Remove(6);
}
void TestR()
{
int array[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9, };
BinarySearchTree<int> tree;
for (size_t index = 0; index < sizeof(array) / sizeof(int); ++index)
{
tree.Insert(array[index]);
}
tree.InOrder();
tree.RemoveR(3);
tree.RemoveR(5);
tree.RemoveR(4);
tree.InOrder();
tree.RemoveR(1);
tree.RemoveR(7);
tree.RemoveR(8);
tree.RemoveR(2);
tree.InOrder();
tree.RemoveR(0);
tree.RemoveR(6);
tree.InOrder();
tree.RemoveR(9);
tree.InOrder();
tree.RemoveR(3);
tree.InOrder();
tree.RemoveR(5);
tree.RemoveR(6);
}
int main()
{
//Test();
TestR();
return 0;
}
KeyValue结构
模拟实现一个简易的翻译工具:
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;
#include<string>
template<class K,class V>
struct BinarySearchTreeNode
{
BinarySearchTreeNode()
:_left(NULL)
, _right(NULL)
{}
BinarySearchTreeNode(const K& key,const V& value)
:_key(key)
, _left(NULL)
, _right(NULL)
, _value(value)
{}
BinarySearchTreeNode<K,V>* _left;
BinarySearchTreeNode<K,V>* _right;
K _key;
V _value;
};
template<class K,class V>
class BinarySearchTree
{
typedef BinarySearchTreeNode<K,V> Node;
public:
BinarySearchTree()
:_root(NULL)
{}
BinarySearchTree(Node* node)
:_root(node)
{}
bool Insert(const K& key,const V& value)
{
if (NULL == _root)
{
_root = new Node(key,value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
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是parent的左孩子还是右孩子
if (key > parent->_key)
{
parent->_right = new Node(key,value);
}
else
{
parent->_left = new Node(key,value);
}
return true;
}
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 NULL;
}
bool Remove(const K& key)
{
Node* cur = _root;
Node* parent = NULL;
Node* del = NULL;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
//1.cur的左为空
if (NULL == cur->_left)
{
del = cur;
if (NULL == parent)//当此时的cur为根节点
{
_root = cur->_right;
}
else if (parent->_left == cur)//cur为parent的左孩子
{
parent->_left = cur->_right;
}
else //cur为parent的右孩子
{
parent->_right = cur->_right;
}
}//2.cur的右为空
else if (NULL == cur->_right)
{
del = cur;
if (NULL == parent)
{
_root = cur->_left;
}
else if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}//3.cur的左右都不为空(替换法删除)
else
{
//①找右子树的最左节点并删除
Node* subRight = cur->_right;
Node* parent = cur;//注意这里的parent不能是NULL(如果右子树的最左节点是根节点循环进去)
while (subRight->_left)
{
parent = subRight;
subRight = subRight->_left;
}
del = subRight;//需要删除的节点
cur->_key = subRight->_key;
//还需判断subRight是parent的左节点还是右节点
if (parent->_left == subRight)
{
parent->_left = subRight->_right;
}
else
{
parent->_right = subRight->_right;
}
}
delete del;
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
~BinarySearchTree()
{
_destory(_root);
}
private:
void _destory(Node* root)
{
if (NULL == root)
{
return;
}
_destory(root->_left);
_destory(root->_right);
delete root;
}
void _InOrder(Node* root)
{
if (NULL == root)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
Node* _root;
};
测试代码:
#include"BinarySearchTree1.h"
//使用KV结构模拟一个简单的翻译工具
void Test()
{
BinarySearchTree<string, string> dict;
dict.Insert("tree","树");
dict.Insert("hello","你好");
BinarySearchTreeNode<string, string>* ret = dict.Find("tree");
if (ret)
{
cout << ret->_value <<endl;
}
string tmp;
while (1)
{
cin >> tmp;
if (dict.Find(tmp))
{
cout << dict.Find(tmp)->_value << endl;
}
}
}
int main()
{
Test();
return 0;
}