当前位置: 首页 > news >正文

c++数据结构--BST树

一.什么是BST树

BST树称作二叉搜索树(Binary Search Tree)或者二叉排序树(Binary Sort Tree),它或者是一颗空树;或者是具有下列性质的二叉树:
1、若左子树不为空,则左子树上所有节点的值均小于它的根节点的值
2、若右子树不为空,则右子树上所有节点的值均大于它的根节点的值
3、左右子树也分别满足二叉搜索树性质

特点:每一个节点都满足 左孩子的值(不为空)<父节点的值<右孩子的值(不为空)

BST树的基本框架

template<typename T, typename Compare = less<T>> class BSTtree { public: BSTtree(Compare comp= Compare()) :root(nullptr) ,comp(comp) { } ~BSTtree() { if (root == nullptr) { return; } queue<Node*>q; q.push(root); while (!q.empty()) { Node* front = q.front(); q.pop(); if (front->left != nullptr) { q.push(front->left); } if (front->right != nullptr) { q.push(front->right); } delete front; } } private: struct Node { Node(T data = T()) :m_data(data) , left(nullptr) , right(nullptr) { } T m_data; Node* left; Node* right; }; Node* root; Compare comp; };

二.BST树常见操作的实现

1.插入

(1)非递归实现

void n_insert(const T& val) { if (root == nullptr) { root = new Node(val); return; } Node* parent = nullptr; Node* cur = root; while (cur != nullptr) { if (comp(val, cur->m_data)) { parent = cur; cur = cur->left; } else if (comp(cur->m_data, val)) { parent = cur; cur = cur->right; } else//不插入相同的值 return; } if (comp(val, parent->m_data)) { parent->left = new Node(val); } else { parent->right = new Node(val); } }

(2)递归实现

//递归插入 void insert(const T& val) { root = insert(root, val); } Node* insert(Node* node, const T& val) { if (node == nullptr) { return new Node(val); } if (node->m_data == val) { return node; } else if (comp(node->m_data, val)) { node->right = insert(node->right, val); } else { node->left = insert(node->left, val); } return node; }

2.删除

(1)非递归实现

void n_remove(const T& val) { if (root == nullptr) { return; } Node* parent = nullptr; Node* cur = root; while (cur != nullptr) { if (comp(val, cur->m_data)) { parent = cur; cur = cur->left; } else if (comp(cur->m_data, val)) { parent = cur; cur = cur->right; } else { break; } } if (cur == nullptr) return; if (cur->left != nullptr && cur->right != nullptr) { parent = cur; Node* pre = cur->left; while (pre->right != nullptr) { parent = pre; pre = pre->right; } cur->m_data = pre->m_data; cur = pre; } Node* child = cur->left; if (child == nullptr) { child = cur->right; } if (parent == nullptr) { root = child; } else { if (parent->left == cur) { parent->left = child; } else { parent->right = child; } } delete cur; }

(2)递归实现

void remove(const T& val) { root = remove(root, val); } Node* remove(Node* node, const T& val) { if (node == nullptr) return nullptr; if (node->m_data == val) { if (node->left != nullptr && node->right != nullptr) { Node* pre = node->left; while (pre->right != nullptr) { pre = pre->right; } node->m_data = pre->m_data; node->left = remove(node->left, pre->m_data); } else { if (node->left != nullptr) { Node* left = node->left; delete node; return left; } else if (node->right != nullptr) { Node* right = node->right; delete node; return right; } else { delete node; return nullptr; } } } else if (comp(node->m_data, val)) { node->right = remove(node->right, val); } else { node->left = remove(node->left, val); } return node; }

3.查找

(1)非递归实现

bool n_find(T val)const { Node* cur = root; while (cur != nullptr) { if (comp(val, cur->m_data)) { cur = cur->left; } else if (comp(cur->m_data, val)) { cur = cur->right; } else { return true; } } return false; }

(2)递归实现

bool find(const T& val) { return find(root, val); } bool find(Node* node, const T& val) { if (node == nullptr) { return false; } if (node->m_data == val) { return true; } else if (comp(node->m_data, val)) { return find(node->right, val); } else { return find(node->left, val); } }

4.前序遍历

(1)非递归实现

void n_preOrder() { if (root == nullptr) { return; } stack<Node*>s; s.push(root); while (!s.empty()) { Node* top = s.top(); s.pop(); cout << top->m_data << " "; if (top->right != nullptr) { s.push(top->right); } if (top->left != nullptr) { s.push(top->left); } } }

(2)递归实现

//递归前序遍历VLR void preOrder() { preOrder(root); } void preOrder(Node* node) { if (node != nullptr) { cout << node->m_data << " "; preOrder(node->left); preOrder(node->right); } }

5.中序遍历

(1)非递归实现

void n_inOrder() { if (root == nullptr) { return; } stack<Node*>s; Node* cur = root; while (cur != nullptr) { s.push(cur); cur = cur->left; } while (!s.empty()) { Node* top = s.top(); s.pop(); cout << top->m_data << " "; cur = top->right; while (cur != nullptr) { s.push(cur); cur = cur->left; } } }

(2)递归实现

//递归中序遍历LVR(中序遍历是升序) void inOrder() { inOrder(root); } void inOrder(Node* node) { if (node != nullptr) { inOrder(node->left); cout << node->m_data << " "; inOrder(node->right); } }

6.后序遍历

(1)非递归实现

void n_postOrder() { if (root == nullptr) { return; } stack<Node*>s1; stack<Node*>s2; s1.push(root); while (!s1.empty()) { Node* top = s1.top(); s1.pop(); s2.push(top); if (top->left != nullptr) { s1.push(top->left); } if (top->right != nullptr) { s1.push(top->right); } } while (!s2.empty()) { Node* cur = s2.top(); cout << cur->m_data << " "; s2.pop(); } }

(2)递归实现

void postOrder() { postOrder(root); } void postOrder(Node* node) { if (node != nullptr) { postOrder(node->left); postOrder(node->right); cout << node->m_data << " "; } }

7.层序遍历

(1)非递归实现

void n_levelOrder() { if (root == nullptr) { return; } queue<Node*>q; q.push(root); while (!q.empty()) { Node* front = q.front(); cout << front->m_data << " "; q.pop(); if (front->left != nullptr) { q.push(front->left); } if (front->right != nullptr) { q.push(front->right); } } }

(2)递归实现

//求BST树的层数 int level() { return level(root); } int level(Node* node) { if (node == nullptr) { return 0; } int left = level(node->left); int right = level(node->right); return left > right ? left + 1 : right + 1; } void levelOrder() { int h = level(); for (size_t i = 0; i < h; i++) { levelOrder(root, i); } } void levelOrder(Node* node, int i) { if (node == nullptr) return; if (i == 0) { cout << node->m_data << " "; return; } levelOrder(node->left, i - 1); levelOrder(node->right, i - 1); }

三.BST树的经典问题

1.区间元素搜索问题

搜索处于i,j之间的所以树上的节点的数据。

(1)非递归实现

//BST树区间元素搜索问题[i,j](非递归实现) void n_findValues(vector<T>& vec, int i, int j) { if (root == nullptr) { return; } stack<Node*>s; Node* cur = root; while (cur != nullptr) { s.push(cur); cur = cur->left; } while (!s.empty()) { Node* top = s.top(); s.pop(); if (top->m_data >= i && top->m_data <= j) { vec.push_back(top->m_data); } cur = top->right; while (cur != nullptr) { s.push(cur); cur = cur->left; } } }

(2)递归实现

void findValues(vector<T>& vec, int i, int j) { findValues(vec, i, j, root); } void findValues(vector<T>& vec, int i, int j, Node* node) { if (node != nullptr) { if (node->m_data >= i) { findValues(vec, i, j, node->left); } if (node->m_data >= 10 && node->m_data <= 50) { vec.push_back(node->m_data); } if (node->m_data <= j) { findValues(vec, i, j, node->right); } } }

2.判断一颗二叉树是否是BST树

bool isBSTtree() { Node* node = nullptr; return isBSTtree(root, node); } bool isBSTtree(Node* node, Node* node2) { if (node == nullptr) { return true; } if (!isBSTtree(node->left, node2)) { return false; } if (node2 != nullptr) { if (node->m_data < node2->m_data) { return false; } } node2 = node; isBSTtree(node->right, node2); }

3.判断一颗二叉树是否是另一颗二叉树的子树

bool isChildtree(BSTtree<T, Compare>& bst) { if (bst.root == nullptr) return true; Node* cur = root; while (cur != nullptr) { if (cur->m_data == bst.root->m_data) { break; } else if (comp(cur->m_data, bst.root->m_data)) { cur = cur->right; } else { cur = cur->left; } } if (cur == nullptr) return false; return isChildtree(cur, bst.root); } bool isChildtree(Node* node, Node* child) { if (node == nullptr && child == nullptr) return true; if (node == nullptr) return false; if (child == nullptr) return true; if (node->m_data != child->m_data) { return false; } return isChildtree(node->left, child->left) && isChildtree(node->right, child->right); }

4.求一个二叉树上两个节点的最近公共祖先节点

int getLCA(int val1, int val2) { Node* node = getLCA(root, val1, val2); if (node == nullptr) throw" NO LCA"; else { return node->m_data; } } Node* getLCA(Node* node, int val1, int val2) { if (node == nullptr) return nullptr; if (node->m_data < val1 && node->m_data < val2) { return getLCA(node = node->right, val1, val2); } else if (node->m_data > val1 && node->m_data > val2) { return getLCA(node = node->left, val1, val2); } else { return node; } }

5.二叉树的镜像翻转问题

//二叉树镜像翻转问题 void mirror() { mirror(root); } void mirror(Node* node) { if (node == nullptr) return; Node* p = nullptr; p = node->left; node->left = node->right; node->right = p; mirror(node->left); mirror(node->right); }

6.二叉树的镜像对称问题

//二叉树镜像对称问题 bool mirror02() { return mirror02(root->left, root->right); } bool mirror02(Node* left, Node* right) { if (left == nullptr && right == nullptr) return true; if (left == nullptr || right == nullptr) return false; if (left->m_data != right->m_data) return false; return mirror02(left->left, right->right) && mirror02(left->right, right->left); }

7.利用先序遍历与中序遍历重建二叉树

Node* _rebuild(int pre[], int i, int j, int in[], int m, int n) { if (i > j || m > n) return nullptr; Node* node = new Node(pre[i]); for (size_t k = m; k <= n; ++k) { if (pre[i] == in[k]) { node->left = _rebuild(pre, i + 1, i + (k - m), in, m, k - 1); node->right = _rebuild(pre, i + (k - m) + 1, j, in, k + 1, n); return node; } } return node; } //根据前序遍历和中序遍历的数组重建二叉树 void rebuild(int pre[], int i, int j, int in[], int m, int n) { root = _rebuild(pre, i, j, in, m, n); }

8.判断一颗二叉树是否是平衡树(AVL树)

//判断一颗二叉树是否是平衡树 bool isBalance() { int l = 0; bool flag = true; isBalance(root, l, flag); return flag; } bool isBalance(Node* node,int l, bool& flag) { if (node == nullptr) { return l; } int left = isBalance(node->left, l + 1, flag); if (!flag) return left; int right = isBalance(node->right, l + 1, flag); if (!flag) return right; if (abs(left - right) > 1) { flag = false; } return max(left, right); }

9.求二叉树中序遍历倒数第k个节点

//求中序遍历倒数第k个节点 int getVal(int k) { int num = 0; Node* node = getVal(root, k,num); if (node == nullptr) { string err = "no NO."; err += k; throw err; } else { return node->m_data; } } Node* getVal(Node* node, int k,int &num) { if (node == nullptr) { return nullptr; } Node* left = getVal(node->right, k,num); if (left != nullptr) return left; num++; if (num == k) { return node; } return getVal(node->left, k,num); }
http://www.jsqmd.com/news/764945/

相关文章:

  • 保姆级教程:用Proxifier给Charles当‘保镖’,轻松抓包Steam、微信PC版等本地应用
  • 2026年铁艺挂饰定制新趋势:品质与价格的完美平衡 - GrowthUME
  • taocp2_rsa_story
  • MCP 2026量子仿真器性能骤降47%?——基于Intel QSC与IBM Qiskit Runtime的基准测试对比报告(限内部白皮书节选)
  • FPGA高速数据缓存实战:基于KCU105的DDR4 MIG IP核完整配置与性能调优指南
  • 告别会员焦虑!用Emby+cpolar在Windows上打造你的私人Netflix(保姆级图文教程)
  • 天津鑫汇达废旧物资回收:天津库存积压回收电话 - LYL仔仔
  • 基于LlamaIndex与本地大模型的私有知识库RAG系统实战指南
  • 通过curl命令快速测试Taotoken大模型API连通性与返回格式
  • 利用快马平台快速生成chromedriver自动化测试原型,验证网页交互逻辑
  • 2025终极指南:LinkSwift网盘直链下载助手 - 告别限速困扰的完整解决方案
  • 2026年餐饮燃料油厂家推荐:学校食堂燃料油/餐饮厨房燃料油/生物油专业供应 - 品牌推荐官
  • AI场景设计框架SCENEWEAVER:3D空间自动布局技术解析
  • 当古老医术遇见现代解剖学:探秘北京黄枢医院的‘针灸微手术’创新实践
  • 去黑头泥膜哪个牌子好 5款大牌泥膜实测!12天清零黑头闭口,缩毛孔淡细纹 - 全网最美
  • AI赋能开发:让快马平台智能生成适应性的OpenClaw抓取规则与代码
  • 2026年5月北京民商事诉讼仲裁/企业法律顾问/二审/再审/民商事案件律师解析,嘉潍律师事务所曹春芳律师 - 2026年企业推荐榜
  • BEVFusion实战:用Python复现MIT版多传感器融合,从环境配置到模型推理保姆级教程
  • Databricks AI Dev Kit:模块化LLM应用开发与RAG生产部署指南
  • iOS游戏模组开发终极指南:H5GG引擎的5个实战技巧
  • 1950-2024年 中国与大国关系数据库(xlsx)
  • 20253915 2024-2025-2 《网络攻防实践》实践9报告 -
  • 2026雅思线上一对一哪家正规?零基础提分靠谱机构推荐与避坑指南 - 品牌2025
  • DeepSeek-671B大模型监督式微调(SFT)实战指南:从原理到部署
  • TargetMol信号通路——PEG300(Cat. No. T7022, CAS. 25322-68-3),常用的体内给药溶剂 - 陶术生物
  • 2026雅思一对一线上辅导选课攻略:拒绝踩坑,精准提分 - 品牌2025
  • 别再手动合并了!用DevExpress GridView实现多条件单元格合并(附完整C#代码)
  • 不同雨课堂版本,更新了新版本,老版本可能无法支持安装了
  • 初次体验 Taotoken 控制台的功能布局与核心操作指引
  • 3分钟搞定AI模型部署!Sakura启动器GUI:零配置本地AI部署终极指南