1.二叉搜索树
1.1 定义
二叉搜索树:
- 一棵非空的二叉搜索树每个元素都有一个关键字,并且任意两个元素的关键字不同,所有关键字都是唯一的
- 根节点的左子树小于根节点的关键字
- 根节点的右子树大于根节点的关键字
- 左右子树也是二叉搜索树
索引二叉搜索树:
源于普通的二叉搜索树,在每个节点中添加一个 leftSize 字段,用来保存该节点左子树的元素个数。
1.2 二叉搜索树的操作和实现
1.2.1 搜索
根据搜索元素的 theKey 对应向左孩子或右孩子移动寻找即可,时间复杂度为O(height)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template<class K, class E> pair<const K, E>* binarySearchTree<K, E>::find(const K& theKey) const { binaryTreeNode<pair<const K, E> >* p = root; while (p != NULL) if (theKey < p->element.first) p = p->leftChild; else if (theKey > p->element.first) p = p->rightChild; else return &p->element;
return NULL; }
|
1.2.2 插入
使用 pp 指针记录 p 指针的双亲节点,p 指针不断查找应该插入的位置
- p 指针指向空时,说明该插入到该位置。判断插入元素 theKey 和 pp 指针的大小关系插入该元素
- p 指针找到相同的 theKey 时,更新该节点的 value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| template<class K, class E> void binarySearchTree<K, E>::insert(const pair<const K, E>& thePair) { binaryTreeNode<pair<const K, E> >* p = root; binaryTreeNode<pair<const K, E> >* pp = NULL;
while (p != NULL) { pp = p; if (thePair.first < p->element.first) p = p->leftChild; else if (thePair.first > p->element.first) p = p->rightChild; else { p->element.second = thePair.second; return; } }
binaryTreeNode<pair<const K, E> >* newNode = new binaryTreeNode<pair<const K, E> >(thePair); if (root != NULL) if (thePair.first < pp->element.first) pp->leftChild = newNode; else pp->rightChild = newNode; else root = newNode; treeSize++; }
|
1.2.3 删除
删除分三种情况
- 要删除的节点没有孩子节点:如左图所示,这种情况只需要找到该节点释放内存空间,并将双亲节点的右孩子指针置为空即可
- 要删除的节点只有一个孩子节点:如右图所示,这种情况只需要将该节点内存空间释放,并且将 元素15 的左孩子连接到 元素12 的孩子节点即可
- 要删除的节点有两个孩子节点,且要更换位置的节点没有孩子节点。我们需要在要删除的节点的左孩子中,向右寻找到最大的元素做替换,将 元素14 重新连接 元素12 和 元素18 构建一个新的树,并重新连接到 元素20 的左孩子位置,最后释放元素14的内存(这种情况实际上转换为构建一棵树,然后删除14,且14没有孩子节点)
- 要删除的节点有两个孩子节点,且要更换位置的节点有一个孩子节点。我们需要在要删除的节点的左孩子中,向右寻找到最大的元素做替换,将 元素14 重新连接 元素12 和 元素18 构建一个新的树,并重新连接到 元素20 的左孩子的位置,然后把 元素14 的孩子连接到 元素14 的双亲节点处,释放 元素14 的内存空间(这种情况实际上转换为构建一棵树,然后删除14,且14有一个孩子节点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| template<class K, class E> void binarySearchTree<K, E>::erase(const K& theKey) {
binaryTreeNode<pair<const K, E> >* p = root; binaryTreeNode<pair<const K, E> >* pp = NULL; while (p != NULL && p->element.first != theKey) { pp = p; if (theKey < p->element.first) p = p->leftChild; else p = p->rightChild; } if (p == NULL) return;
if (p->leftChild != NULL && p->rightChild != NULL) { binaryTreeNode<pair<const K, E>>* s = p->leftChild; binaryTreeNode<pair<const K, E>>* ps = p; while (s->rightChild != NULL) { ps = s; s = s->rightChild; }
binaryTreeNode<pair<const K, E> >* q = new binaryTreeNode<pair<const K, E>> (s->element, p->leftChild, p->rightChild);
if (pp == NULL) { root = q; } else if (p == pp->leftChild) { pp->leftChild = q; } else { pp->rightChild = q; }
if (ps == p) { pp = q; } else { pp = ps; }
delete p; p = s; }
binaryTreeNode<pair<const K, E> >* c; if (p->leftChild != NULL) { c = p->leftChild; } else if (p->leftChild != NULL) { c = p->rightChild; } else { c = NULL; }
if (p == root) root = c; else { if (p == pp->leftChild) pp->leftChild = c; else pp->rightChild = c; } treeSize--; delete p; }
|
Author:
mxwu
Permalink:
https://mingxuanwu.com/2023/10/13/202310132010/
License:
Copyright (c) 2023 CC-BY-NC-4.0 LICENSE