目录
一 概念
二 二叉树基础构建
三 二叉搜索树的查找
四 二叉搜索树的插入
五 二叉搜索树的删除
六 总结
一 概念
- 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树
- 二叉搜索树遍历一遍,就可以得到一个有序序列,因此,时间复杂度为O(N)
- 二叉搜索树最差情况下会退化为单支树,因此:其查找的效率为O(N)
二 二叉树基础构建
template<class K>
struct BSTreeNode
{typedef BSTreeNode<K> Node;K _key;Node* _left;Node* _right;BSTreeNode(const K& key){_key = key;_left = nullptr;_right = nullptr;}};template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:BSTree() = default;BSTree(const BSTree<K>& t){_root = Copy(t._root);}Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newRoot = new Node(root->_key);newRoot->_left = Copy(root->_left);newRoot->_right = Copy(root->_right);return newRoot;}BSTree<T>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}void Inorder(){_Inorder(_root);cout << endl;}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_key << " ";_Inorder(root->_right);}~BSTree(){Destroy(_root);}void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;}private:Node* _root = nullptr;};
三 二叉搜索树的查找
a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。
bool 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 true;}}return false;}
四 二叉搜索树的插入
a.树为空,则直接新增节点,赋值给root指针
b.树不空,按二叉搜索树性质查找插入位置,插入新节点
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;}elsereturn false;}cur = new Node(key);if (parent->_key > key){parent->_left = cur;}else{parent->_right = cur;}return true;}
五 二叉搜索树的删除
首先查找元素是否在二叉搜索树中,如果不存在则返回, 否则要删除的结点可能分下面四种情况:
a.要删除的结点无孩子结点
b.要删除的结点只有左孩子结点
c.要删除的结点只有右孩子结点
d.要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除
bool Erase(const K& key){Node* cur = _root;Node* parent = cur;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;return true;}//只有左节点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;return true;}//左右节点都有else{Node* parentMin = cur;Node* rightMinNode = cur->_right;while (rightMinNode->_left){parentMin = rightMinNode;rightMinNode = rightMinNode->_left;}//赋值cur->_key = rightMinNode->_key;if (parentMin->_left = rightMinNode){parentMin->_left = rightMinNode->_right;}else{parentMin->_right = rightMinNode->_right;}delete rightMinNode;return true;}}}return false;}
六 总结
#pragma oncetemplate<class K>
struct BSTreeNode
{typedef BSTreeNode<K> Node;K _key;Node* _left;Node* _right;BSTreeNode(const K& key){_key = key;_left = nullptr;_right = nullptr;}};template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:BSTree() = default;BSTree(const BSTree<K>& t){_root = Copy(t._root);}BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}void Inorder(){_Inorder(_root);cout << endl;}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_key << " ";_Inorder(root->_right);}~BSTree(){Destroy(_root);}bool 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 true;}}return false;}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;}elsereturn false;}cur = new Node(key);if (parent->_key > key){parent->_left = cur;}else{parent->_right = cur;}return true;}bool Erase(const K& key){Node* cur = _root;Node* parent = cur;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;return true;}//只有左节点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;return true;}//左右节点都有else{Node* parentMin = cur;Node* rightMinNode = cur->_right;while (rightMinNode->_left){parentMin = rightMinNode;rightMinNode = rightMinNode->_left;}//赋值cur->_key = rightMinNode->_key;if (parentMin->_left = rightMinNode){parentMin->_left = rightMinNode->_right;}else{parentMin->_right = rightMinNode->_right;}delete rightMinNode;return true;}}}return false;}private:void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;}Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newRoot = new Node(root->_key);newRoot->_left = Copy(root->_left);newRoot->_right = Copy(root->_right);return newRoot;}Node* _root = nullptr;};
下个章节是 搜索二叉树的应用, 本节是应用和Hash的重要基础. 继续加油!