文章目录

  • 二叉搜索树
  • 索引二叉搜索树
  • 测试代码

这里只给出代码实现。
更多的性质日后再补。

二叉搜索树

//
// Created by SongyangJi on 2020/12/23.
//#ifndef DATASTRUCTURE_BINARYSEARCHTREE_H
#define DATASTRUCTURE_BINARYSEARCHTREE_H#include<iostream>using std::ostream;
using std::endl;
using std::cout;template<class K, class V>
class BinarySearchTree {private:struct Node {K key;V value;Node *left = nullptr, *right = nullptr;Node(const K &key, const V &value) : key(key), value(value) {}friend ostream &operator<<(ostream &os, Node &node) {os << "{ key: " << node.key << " , " << " value: " << node.value << "}" << endl;return os;}};Node *root = nullptr;Node *find(Node *node, const K &k) const {if (node->key == k) {return node;}if (k < node->key) {return find(node->left, k);} else {return find(node->right, k);}}void insert(Node *&node, const K &k, const V &v) {if (node == nullptr) {node = new Node(k, v);return;}if (k < node->key) {insert(node->left, k, v);} else if (k > node->key) {insert(node->right, k, v);} else {// 键相同,值被覆盖node->value = v;}}//  分成两种情况 递归实现void erase(Node *&node, const K &k) {if (node == nullptr) return;if (k < node->key) {erase(node->left, k);} else if (k > node->key) {erase(node->right, k);} else {// 叶节点直接删除if (node->left == nullptr && node->right == nullptr) {delete node;node = nullptr;} else if (node->left != nullptr) {// 找到前驱代替Node* pre = node->left;while(pre->right != nullptr){pre = pre->right;}node->key = pre->key;node->value = pre->value;erase(node->left,pre->key);} else {// 找到后继代替Node* next = node->right;while(next->left != nullptr){next = next->left;}node->key = next->key;node->value = next->value;erase(node->right,next->key);}}}// 细分成三种情况,迭代实现void _erase(Node *&node,const K &k){//第一步:查找关键字为 key 的节点// p 是移动的指针、 pp 是 p 的父亲节点Node *p = node, *pp = nullptr;while(p != nullptr && p->key != k){pp = p;if(k < p->key){p = p->left;}else{p = p->right;}}// p 为空, 表明没找到 key ,就不删if(p==nullptr) return ;// 第二步:情况根据 p 的子树情况分别处理// 第一种情况:p 是叶子节点if(p->left == nullptr && p->right == nullptr){if(p == root){root = nullptr;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = nullptr;}else{pp->right = nullptr;}}delete p;// 第二种情况:p 只有一个子树}else if(p->left != nullptr && p->right == nullptr){if(p == root){root =  p->left;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = p->left;}else{pp->right = p->left;}}delete p;}else if(p->right != nullptr && p->left == nullptr){if(p == root){root = p->right;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = p->right;}else{pp->right = p->right;}}delete p;// 第三种情况:也是最复杂的情况,p左右子树都不为空// 解决方案:用 前驱/后继 的值代替 p 的值,再去删除 前驱/后继// 之所以这是可行的,是因为 前驱/后继必然最多拥有一棵子树(如果不是,说明// 那根本就不是前驱或后继,而这时问题就是前面已经处理过的了}else{// 假定现在我们用前驱代替(用后继代替也是一样)// 前驱:左子树最右边的节点Node* cur = p->left;while(cur->right!=nullptr){cur = cur->right;}p->key = cur->key;p->value = cur->value;// 注意这个函数不会一直调用下去,只会调用一次,因为可以保证 节点cur就是第一、二种情况_erase(p->left,cur->key);}}void helperDestructor(Node *node) {if (node == nullptr) return;helperDestructor(node->left);helperDestructor(node->right);cout<<"析构 "<<*node;delete node;}void inOrder(Node *node) {if (node == nullptr) return;inOrder(node->left);cout << *node;inOrder(node->right);}public:typedef Node *TreeNode;TreeNode find(const K &k) const {return find(root, k);}void insert(const K &k, const V &v) {insert(root, k, v);}void erase(const K &k) {_erase(root,k);}void ascend() {inOrder(root);}virtual ~BinarySearchTree() {helperDestructor(root);}};#endif //DATASTRUCTURE_BINARYSEARCHTREE_H

索引二叉搜索树

//
// Created by SongyangJi on 2020/12/23.
//#ifndef DATASTRUCTURE_INDEXEDBINARYSEARCHTREE_H
#define DATASTRUCTURE_INDEXEDBINARYSEARCHTREE_H#include<iostream>using std::ostream;
using std::endl;
using std::cout;template<class K,class V>
class IndexedBinarySearchTree {private:struct Node {K key;V value;int leftSize = 0;Node *left = nullptr, *right = nullptr;Node(const K &key, const V &value) : key(key), value(value) {}friend ostream &operator<<(ostream &os, Node &node) {os << "{ key: " << node.key << " , " << " value: " << node.value << "}" << endl;return os;}};Node *root = nullptr;int numOfNodes = 0;Node* find(Node *node, const K &k) const {if(node == nullptr) return nullptr;if (node->key == k) {return node;}if (k < node->key) {return find(node->left, k);} else {return find(node->right, k);}}void insert(Node *&node, const K &k, const V &v) {if (node == nullptr) {node = new Node(k, v);return;}if (k < node->key) {insert(node->left, k, v);// 向左边插入, leftSize 要自增1node->leftSize++;} else if (k > node->key) {insert(node->right, k, v);} else {// 键相同,值被覆盖node->value = v;}}//  分成两种情况 递归进行删除void erase(Node *&node, const K &k) {if (node == nullptr) return;if (k < node->key) {erase(node->left, k);// 更新 leftSizenode->leftSize--;} else if (k > node->key) {erase(node->right, k);} else {// 叶节点直接删除if (node->left == nullptr && node->right == nullptr) {delete node;node = nullptr;} else if (node->left != nullptr) {// 找到前驱代替Node* pre = node->left;while(pre->right != nullptr){pre = pre->right;}node->key = pre->key;node->value = pre->value;erase(node->left,pre->key);// 注意node->leftSize--;} else {// 找到后继代替Node* next = node->right;while(next->left != nullptr){next = next->left;}node->key = next->key;node->value = next->value;erase(node->right,next->key);}}}// 细分成三种情况,迭代实现void _erase(Node *&node,const K &k){//第一步:查找关键字为 key 的节点// p 是移动的指针、 pp 是 p 的父亲节点Node *p = node, *pp = nullptr;while(p != nullptr && p->key != k){pp = p;if(k < p->key){// 更新 leftSizep->leftSize--;p = p->left;}else{p = p->right;}}// p 为空, 表明没找到 key ,就不删if(p==nullptr) return ;// 第二步:情况根据 p 的子树情况分别处理// 第一种情况:p 是叶子节点if(p->left == nullptr && p->right == nullptr){if(p == root){root = nullptr;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = nullptr;}else{pp->right = nullptr;}}delete p;// 第二种情况:p 只有一个子树,是左子树}else if(p->left != nullptr && p->right == nullptr){if(p == root){root =  p->left;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = p->left;}else{pp->right = p->left;}}delete p;// 第二种情况:p 只有一个子树,是右子树}else if(p->right != nullptr && p->left == nullptr){if(p == root){root = p->right;}else{// 判断 p 是 pp 的左/右孩子if(p == pp->left){pp->left = p->right;}else{pp->right = p->right;}}delete p;// 第三种情况:也是最复杂的情况,p左右子树都不为空// 解决方案:用 前驱/后继 的值代替 p 的值,再去删除 前驱/后继// 之所以这是可行的,是因为 前驱/后继必然最多拥有一棵子树(如果不是,说明// 那根本就不是前驱或后继,而这时问题就是前面已经处理过的了}else{// 现在我们用后继代替(这样 leftSiz无需变动)// 后继:右子树最左边的节点Node* cur = p->right;while(cur->left!=nullptr){cur = cur->left;}p->key = cur->key;p->value = cur->value;// 注意这个函数不会一直调用下去,只会调用一次,因为可以保证 节点cur就是第一、二种情况_erase(p->right,cur->key);}}Node* get(Node *node,int index) const {if(index == node->leftSize){return node;}else if(index < node->leftSize){return get(node->left,index);}else{return get(node->right,index-node->leftSize-1);}}void helperDestructor(Node *node) {if (node == nullptr) return;helperDestructor(node->left);helperDestructor(node->right);cout<<"析构 "<<*node;delete node;}void inOrder(Node *node) {if (node == nullptr) return;inOrder(node->left);cout << *node;inOrder(node->right);}public:typedef Node *TreeNode;TreeNode find(const K &k) const {return find(root, k);}void insert(const K &k, const V &v) {numOfNodes++;insert(root, k, v);}void erase(const K &k) {// 先判断 键为 k 的节点是否在树中if(find(root,k) == nullptr){return;}numOfNodes--;_erase(root,k);}void ascend() {inOrder(root);}TreeNode get(int index) const{if(index >= numOfNodes){return nullptr;}return get(root,index);}void remove(int index){if(index >= numOfNodes){return;}Node* node = get(index);erase(node->key);}virtual ~IndexedBinarySearchTree() {helperDestructor(root);}};#endif //DATASTRUCTURE_INDEXEDBINARYSEARCHTREE_H

测试代码

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>using namespace std;#include "binaryTree/BinarySearchTree.h"
#include "binaryTree/IndexedBinarySearchTree.h"int main(){IndexedBinarySearchTree<int,string> binarySearchTree;binarySearchTree.insert(3,"王五");binarySearchTree.insert(1,"张三");binarySearchTree.insert(2,"李四");binarySearchTree.insert(5,"Mike");binarySearchTree.insert(7,"Lina");binarySearchTree.insert(6,"Green");//    binarySearchTree.insert(7,"Lina");
//    binarySearchTree.insert(6,"Green");
//    binarySearchTree.insert(5,"Mike");
//    binarySearchTree.insert(3,"王五");
//    binarySearchTree.insert(2,"李四");
//    binarySearchTree.insert(1,"张三");//    IndexedBinarySearchTree<int,string>::TreeNode treeNode = binarySearchTree.find(2);
//    cout<<*treeNode;
//    cout<<endl;
//    treeNode->value = "李四儿";binarySearchTree.ascend();cout<<endl;IndexedBinarySearchTree<int,string>::TreeNode treeNode0 =  binarySearchTree.get(0);IndexedBinarySearchTree<int,string>::TreeNode treeNode1 =  binarySearchTree.get(1);IndexedBinarySearchTree<int,string>::TreeNode treeNode2 =  binarySearchTree.get(2);cout<<*treeNode0;cout<<*treeNode1;cout<<*treeNode2;binarySearchTree.erase(1);binarySearchTree.erase(2);binarySearchTree.erase(10);cout<<"to  "<<endl;binarySearchTree.ascend();cout<<"to  "<<endl;IndexedBinarySearchTree<int,string>::TreeNode treeNode0_0 =  binarySearchTree.get(0);IndexedBinarySearchTree<int,string>::TreeNode treeNode0_1 =  binarySearchTree.get(1);cout<<*treeNode0_0;cout<<*treeNode0_1;cout<<endl;binarySearchTree.ascend();binarySearchTree.remove(0);binarySearchTree.remove(1);cout<<endl<<endl;binarySearchTree.ascend();return 0;
}

平衡搜索树(Binary Search Tree BST)、索引二叉搜索树相关推荐

  1. 96. Unique Binary Search Trees 不同的二叉搜索树

    Title 给定一个整数 n,求以 1 - n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1\ ...

  2. 实现一个二叉搜索树(Binary Search Tree)

    文章目录 定义 代码实现 一.Github代码地址 二.节点 三.树实现接口 四.4种遍历方式 五.搜索 六.删除 七.插入 结尾 定义 二叉搜索树(Binary Search Tree),又名二叉排 ...

  3. C++二叉搜索树(Binary Search Tree)(附完整源码)

    二叉搜索树Binary Search Tree node结构体定义 Queue结构体定义 二叉搜索树Binary Search Tree算法的完整源码(定义,实现,main函数测试) node结构体定 ...

  4. 数据结构与算法(八)二分搜索树(Binary Search Tree)

    本文主要包括以下内容: 二分搜索树的基本概念 二分搜索树的基本操作 1. 插入 2. 删除 3. 查询 实现二分搜索树 二分搜索树的不足 二分搜索树的基本概念 二分搜索树(英语:Binary Sear ...

  5. BST(二叉搜索树)

    BST(二叉搜索树) 所谓二叉搜索树(Binary Search Tree,简称 BST)大家应该都不陌生,它是一种特殊的二叉树. 特殊在哪里呢? 简单来说就是:左小右大 BST的完整定义如下: BS ...

  6. 【数据结构与算法】之深入解析“把二叉搜索树转换为累加树”和“从二叉搜索树到更大和树”的求解思路与算法示例

    一.题目要求 ① 把二叉搜索树转换为累加树 给出二叉搜索树的根节点,该树的节点值各不相同,请将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 no ...

  7. 二叉搜索树(Binary Search Tree)(Java实现)

    文章目录 1.二叉搜索树 1.1. 基本概念 1.2.树的节点(BinaryNode) 1.3.构造器和成员变量 1.3.公共方法(public method) 1.4.比较函数 1.5.contai ...

  8. UVA 1264 - Binary Search Tree(BST+计数)

    UVA 1264 - Binary Search Tree 题目链接 题意:给定一个序列,插入二叉排序树,问有多少中序列插入后和这个树是同样的(包含原序列) 思路:先建树,然后dfs一遍,对于一个子树 ...

  9. 树、二叉树、二叉搜索树_检查二叉树是否为BST(二叉搜索树)

    树.二叉树.二叉搜索树 Description: 描述: This article describes how to check whether a given tree is BST or not? ...

最新文章

  1. 详细的线程池讲解,手写C与C++版本
  2. Nature:初步探索限制饮食如何影响肿瘤生长
  3. 用拦截器+注解+cookie进行简单限流访问案例
  4. C# 中的char 和 byte
  5. openssh升级sftp_OpenSSH 8.2 发布 包括 sftp 客户端和服务器支持
  6. 阿里P8成长路线!我的头条面试经历分享,吊打面试官系列!
  7. C++单元测试框架的比较(zz)
  8. 如何检测支付宝接口中notify_url.php有没有返回,微信小程序支付成功,但是notify_url接收不到回调如何排查此问题?...
  9. ubuntu下面如何切换virtual_box的鼠标
  10. Atiti.ui原理与gui理论
  11. flask中的csrf防御机制
  12. npm connect ETIMEDOUT
  13. 调频连续波雷达(FMCW)测距/测速原理
  14. 【程序员学理财】有哪些普通人应该知道的经济学常识?
  15. Makefile + vcs + dve
  16. 鸟枪换炮---IDEA
  17. java3D实现空间立方体,纯CSS3实现一个旋转的3D立方体盒子
  18. 《实战 Java 高并发程序设计》笔记——第3章 JDK 并发包(二)
  19. signal,blinker:信号(看我脸色行事)
  20. js对象是什么?js对象类型有哪些?js对象类型的总结

热门文章

  1. 游戏联运平台到底靠不靠谱?
  2. 天天加班,你以为你就可以升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰了么?
  3. 《MATLAB智能算法30个案例》:第16章 基于动态粒子群算法的动态环境寻优算法
  4. 在医疗保健中使用GIS技术有哪些好处
  5. 局部解剖学名词解释及大题
  6. 第5章 运算符和表达式
  7. 菊风亮相2020中国移动全球合作伙伴大会,共谱数智未来
  8. 历史学家揭秘武则天母女共用男宠
  9. web3.0是什么?
  10. 凌云库存管理系统的几点使用心得