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

工业b2b网站建设台州seo排名外包

工业b2b网站建设,台州seo排名外包,苏州企业建站程序,深圳设计平台文章目录 二叉搜索树二叉搜索树的模拟实现构造函数拷贝构造函数赋值运算符重载函数析构函数Insert循环递归 Erase循环递归 Find循环递归 二叉搜索树的应用K模型KV模型 完整代码普通版本递归版本 二叉搜索树 二叉搜索树又称为二叉排序树,它或者是一棵空树&#xff0…

文章目录

  • 二叉搜索树
  • 二叉搜索树的模拟实现
  • 构造函数
  • 拷贝构造函数
  • 赋值运算符重载函数
  • 析构函数
  • Insert
    • 循环
    • 递归
  • Erase
    • 循环
    • 递归
  • Find
    • 循环
    • 递归
  • 二叉搜索树的应用
  • K模型
    • KV模型
  • 完整代码
    • 普通版本
    • 递归版本

二叉搜索树

二叉搜索树又称为二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

若它的左子树不为空,
则左子树上所有结点的值都小于根结点的值。

若它的右子树不为空,
则右子树上所有结点的值都大于根结点的值。

它的左右子树也分别是二叉搜索树。

在这里插入图片描述

二叉搜索树的模拟实现

构造函数

	BSTree():_root(nullptr){}

拷贝构造函数

	BSTree(const  BSTree<K>& t)//BSTree(  BSTree<K>  *this ,  const  BSTree<K> & t)//t1 =t {_root = Copy(t._root);}private:Node* Copy(Node* root){if (root == nullptr){return nullptr;}Node* copyNode = new Node(root->_key);//递归 copyNode->_left = Copy(root->_left);copyNode->_right = Copy(root->_right);return  copyNode;}

赋值运算符重载函数

	//赋值重载 BSTree<K>& operator= (BSTree<K>& t)//t1 = t//深拷贝{swap(_root, t._root);return *this;}

析构函数

~BSTree(){Destroy(_root);}private:void Destroy(Node*& root) //引用的目的:将每个节点释放后同时置空{//后序遍历 if (root == nullptr){return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}

Insert

核心思路:

如果是空树,则直接将插入结点作为二叉搜索树的根结点。

如果不是空树,则按照二叉搜索树的性质进行结点的插入。
如果待插入结点的值<根结点的值,则需要将结点插入到左子树当中。
如果待插入结点的值>根结点的值,则需要将结点插入到右子树当中。
如果待插入结点的值等于根结点的值,则插入失败。

循环

bool Insert(const K & key ){//空树if (_root == nullptr){_root = new Node(key);return true;}//不是空树Node* parent = nullptr;//找到父节点Node* cur = _root;while (cur){//比较if (cur->_key < key){//往右子树走parent = cur;cur  = cur->_right;}else if (cur->_key > key){//往左子树走parent = cur;cur = cur->_left;}else{return false;}}//插入节点cur = new Node(key);//不知道parent在那一边,需要进一步判断if (parent->_key > key){//parent在左边parent->_left = cur;}else if (parent->_key < key){//parent在右边parent->_right = cur;}else{return false;}return true;}

递归

	bool InsertR(const K& key)//递归版本{return _InsertR(_root, key);}private:bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父节点,不需要用父节点比较大小{//结束条件if (root == nullptr){root = new Node(key);return true;}//往左子树走if (root->_key > key){return _InsertR(root->_left, key);}//往右子树走else if (root->_key < key){return _InsertR(root->_right, key);}else{return false;}}

Erase

先找到需要删除的节点
需要删除的节点可能会有三种情况:
1、待删除结点的左子树为空(待删除结点的左右子树均为空包含在内)

在这里插入图片描述

2、待删除结点的右子树为空。
在这里插入图片描述

1、2 两种情况,被删除的节点都只有一个孩子

3、待删除结点的左右子树均不为空,即被删除节点有两个孩子
使用替换法处理第3中情况:
1、找替换节点:替换节点一般是左子树的最大节点(最右节点),或者是右子树的最小节点(最左节点)
2、将替换的节点删除

在这里插入图片描述
特殊情况:

在这里插入图片描述

循环

	bool Erase(const K& key){Node* parent = nullptr;//待删除节点的父节点Node* cur = _root;//待删除的节点//不是空树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;}//待删除节点不是根节点,并且此时parent不为nullptrelse{if (parent->_right == cur){parent->_right = cur->_right;}else//parent->_left ==cur{parent->_left = cur->_right;}}}//待删除节点的右子树为空 ,即一个孩子的情况else if (cur->_right == nullptr){//待删除节点是根节点if (cur == _root){//将根节点改为待删除节点的左孩子_root = cur->_left;}//待删除节点不是根节点,并且此时parent不为nullptrelse{if (parent->_right == cur){parent->_right = cur->_left;}else//parent->_left==cur{parent->_left = cur->_left;}}} else //待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除){//替换法//找替代节点Node* parent = cur;//找左子树的最大节点,左子树的最大节点一定没有右孩子Node* leftMax = cur->_left;while (leftMax->_right){parent = leftMax; //记录leftMax的父节点,防止删除leftMax时找不到该节点位置 //一直往右子树找leftMax = leftMax->_right;}//左子树的最大节点和待删除节点替换swap(cur->_key, leftMax->_key);//重新改变链接关系//特殊情况 if (parent->_left == leftMax){parent->_left = leftMax->_left;}else//普通情况 parent->_right== leftMax{parent->_right = leftMax->_left;}cur = leftMax;}//删除左子树的最大节点delete cur;return true;}}return false;}

递归

	bool EraseR(Node* _root, const K& key)//递归版本{return _EraseR(_root, key);}private:bool _EraseR(Node*& root, const K& key)//引用的目的:不用找父节点,不需要用父节点比较大小{//结束条件if (root == nullptr){return false;}//往左树找if (root->_key > key){return _EraseR(root->_left, key);}//往右树找else if (root->_key < key){return _EraseR(root->_right, key);}else//找到,开始删除{Node* del = root;//待删除节点的左子树为空 ,即一个孩子的情况if (root->_left == nullptr){root = root->_right;}//待删除节点的右子树为空 ,即一个孩子的情况else if (root->_right == nullptr){root = root->_left;}//待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)else{//找左子树最大节点Node* leftMax = root->_left;//一直往左边找,直到找到左子树最大节点while (root->_left){root = root->_left;}//将左子树最大节点与被删除节点替换swap(leftMax->_key, root->_key);return _EraseR(root, key);}delete del;//?return true;}}

Find

循环

	bool Find(const K & key){Node* cur = _root;while (cur){if (cur->_left > key){cur = cur->_left;}else if (cur->_left < key){cur = cur->_right;}else{return false;}return true;}}

递归

	bool FindR(Node* _root, const K& key)//递归版本{return _FindR(_root, key);}private:bool  _FindR(Node* root, const K& key){//结束条件if (root == nullptr){return false;}if (root->_key > key){return _FindR(root->_left, key);}else if (root->_key < key){return _FindR(root->_right, key);}else{return true;}}

二叉搜索树的应用

K模型

K模型,即只有key作为关键码,结构中只需存储key即可,关键码即为需要搜索到的值。

比如:给定一个单词,判断该单词是否拼写正确。具体方式如下:

	void TestBSTree1(){BSTree<string, string > dict;dict.InsertR("insert", "插入");dict.InsertR("sort", "排序");dict.InsertR("right", "右边");dict.InsertR("date", "日期");string str;while (cin>>str){auto * ret  = dict.FindR(str);//auto ret = dict.FindR(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}}

KV模型

KV模型,对于每一个关键码key,都有与之对应的值value,即<key, value>的键值对。

英汉词典就是英文与中文的对应关系,即<word, Chinese>就构成一种键值对。具体方式如下

1、以<单词, 中文含义>为键值对,构建一棵二叉搜索树。注意:二叉搜索树需要进行比较,键值对比较时只比较key。
2、查询英文单词时,只需给出英文单词就可以快速找到与其对应的中文含义。

完整代码

普通版本

#pragma once template <class K>struct BSTreeNode
{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K & key):_left(nullptr),_right(nullptr),_key(key){}
};template <class K> 
class BSTree
{typedef  BSTreeNode<K> Node;
public:BSTree():_root(nullptr){}bool Insert(const K & key ){//空树if (_root == nullptr){_root = new Node(key);return true;}//不是空树Node* parent = nullptr;//找到父节点Node* cur = _root;while (cur){//比较if (cur->_key < key){//往右子树走parent = cur;cur  = cur->_right;}else if (cur->_key > key){//往左子树走parent = cur;cur = cur->_left;}else{return false;}}//插入节点cur = new Node(key);//不知道parent在那一边,需要进一步判断if (parent->_key > key){//parent在左边parent->_left = cur;}else if (parent->_key < key){//parent在右边parent->_right = cur;}else{return false;}return true;}bool Find(const K & key){Node* cur = _root;while (cur){if (cur->_left > key){cur = cur->_left;}else if (cur->_left < key){cur = cur->_right;}else{return false;}return true;}}bool Erase(const K& key){Node* parent = nullptr;//待删除节点的父节点Node* cur = _root;//待删除的节点//不是空树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;}//待删除节点不是根节点,并且此时parent不为nullptrelse{if (parent->_right == cur){parent->_right = cur->_right;}else//parent->_left ==cur{parent->_left = cur->_right;}}}//待删除节点的右子树为空 ,即一个孩子的情况else if (cur->_right == nullptr){//待删除节点是根节点if (cur == _root){//将根节点改为待删除节点的左孩子_root = cur->_left;}//待删除节点不是根节点,并且此时parent不为nullptrelse{if (parent->_right == cur){parent->_right = cur->_left;}else//parent->_left==cur{parent->_left = cur->_left;}}} else //待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除){//替换法//找替代节点Node* parent = cur;//找左子树的最大节点Node* leftMax = cur->_left;while (leftMax->_right){parent = leftMax; //记录leftMax的父节点,防止删除leftMax时找不到该节点位置 //一直往右子树找leftMax = leftMax->_right;}//左子树的最大节点和待删除节点替换swap(cur->_key, leftMax->_key);//重新改变链接关系//特殊情况 if (parent->_left == leftMax){parent->_left = leftMax->_left;}else//普通情况 {parent->_right = leftMax->_left;//parent->_right =nullptr;}cur = leftMax;}//删除左子树的最大节点delete cur;return true;}}return false;}//中序遍历void InOrder(){_InOrder(_root);cout << endl;}void _InOrder(Node *root  ){if (root == nullptr){return; }_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root;
};void TestBSTree1()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.Insert(e);}t.InOrder();t.Erase(4);t.InOrder();t.Erase(6);t.InOrder();t.Erase(7);t.InOrder();t.Erase(3);t.InOrder();for (auto e : a){t.Erase(e);}t.InOrder();}

递归版本

#pragma once 
#include<string>
using namespace std;
namespace key
{template <class K>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};template <class K>class BSTree{public:typedef  BSTreeNode<K> Node;public:BSTree():_root(nullptr){}~BSTree(){Destroy(_root);}//拷贝构造BSTree(const  BSTree<K>& t)//BSTree(  BSTree<K>  *this ,  const  BSTree<K> & t)//t1 =t {_root = Copy(t._root);}//赋值重载 BSTree<K>& operator= (BSTree<K>& t)//t1 = t{swap(_root, t._root);return *this;}bool EraseR(Node* _root, const K& key)//递归版本{return _EraseR(_root, key);}bool InsertR(const K& key)//递归版本{return _InsertR(_root, key);}bool FindR(Node* _root, const K& key)//递归版本{return _FindR(_root, key);}private:Node* Copy(Node* root){if (root == nullptr){return nullptr;}Node* copyNode = new Node(root->_key);//递归 copyNode->_left = Copy(root->_left);copyNode->_right = Copy(root->_right);return  copyNode;}void Destroy(Node*& root) //引用的目的:将每个节点释放后同时置空{//后序遍历 if (root == nullptr){return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父节点,不需要用父节点比较大小{//结束条件if (root == nullptr){root = new Node(key);return true;}//往左子树走if (root->_key > key){return _InsertR(root->_left, key);}//往右子树走else if (root->_key < key){return _InsertR(root->_right, key);}else{return false;}}bool _EraseR(Node*& root, const K& key)//引用的目的:不用找父节点,不需要用父节点比较大小{//结束条件if (root == nullptr){return false;}//往左树找if (root->_key > key){return _EraseR(root->_left, key);}//往右树找else if (root->_key < key){return _EraseR(root->_right, key);}else//找到,开始删除{Node* del = root;//待删除节点的左子树为空 ,即一个孩子的情况if (root->_left == nullptr){root = root->_right;}//待删除节点的右子树为空 ,即一个孩子的情况else if (root->_right == nullptr){root = root->_left;}//待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)else{//找左子树最大节点Node* leftMax = root->_left;//一直往左边找,直到找到左子树最大节点while (root->_left){root = root->_left;}//将左子树最大节点与被删除节点替换swap(leftMax->_key, root->_key);return _EraseR(root, key);}delete del;//?return true;}}bool  _FindR(Node* root, const K& key){//结束条件if (root == nullptr){return false;}if (root->_key > key){return _FindR(root->_left, key);}else if (root->_key < key){return _FindR(root->_right, key);}else{return true;}}public://中序遍历void InOrder(){_InOrder(_root);cout << endl;}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}public:Node* _root;};void TestBSTree1(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.InsertR(e);}t.InOrder();//没有引用,释放了,只是指针没有置空,尤其是根节点_root,我们还能通过他找到/*t.Destroy(t._root);*/t.EraseR(t._root, 4);t.InOrder();t.EraseR(t._root, 6);t.InOrder();t.EraseR(t._root, 7);t.InOrder();t.EraseR(t._root, 3);t.InOrder();for (auto e : a){t.EraseR(t._root, e);}t.InOrder();}void TestBSTree2(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> t;for (auto e : a){t.InsertR(e);}t.InOrder();BSTree<int> t1(t);t.InOrder();t1.InOrder();}
}namespace key_value
{template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>class BSTree{public:typedef BSTreeNode<K, V> Node;public:BSTree():_root(nullptr){}void InOrder(){_InOrder(_root);cout << endl;}Node* FindR(const K& key){return _FindR(_root, key);}bool InsertR(const K& key, const V& value){return _InsertR(_root, key, value);}bool EraseR(const K& key){return _EraseR(_root, key);}private:bool _EraseR(Node*& root, const K& key){if (root == nullptr)return false;if (root->_key < key){return _EraseR(root->_right, key);}else if (root->_key > key){return _EraseR(root->_left, key);}else{Node* del = root;// 1、左为空// 2、右为空// 3、左右都不为空if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{Node* leftMax = root->_left;while (leftMax->_right){leftMax = leftMax->_right;}swap(root->_key, leftMax->_key);return _EraseR(root->_left, key);}delete del;return true;}}bool _InsertR(Node*& root, const K& key, const V& value){if (root == nullptr){root = new Node(key, value);return true;}if (root->_key < key){return _InsertR(root->_right, key, value);}else if (root->_key > key){return _InsertR(root->_left, key, value);}else{return false;}}Node* _FindR(Node* root, const K& key){if (root == nullptr)return nullptr;if (root->_key < key){return _FindR(root->_right, key);}else if (root->_key > key){return _FindR(root->_left, key);}else{return root;}}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root;};void TestBSTree1(){BSTree<string, string > dict;dict.InsertR("insert", "插入");dict.InsertR("sort", "排序");dict.InsertR("right", "右边");dict.InsertR("date", "日期");string str;while (cin>>str){auto * ret  = dict.FindR(str);//auto ret = dict.FindR(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}}void TestBSTree2(){string arr[] = {"西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };BSTree<string, int > countTree;for (auto &str : arr){auto ret = countTree.FindR(str);if (ret == nullptr){countTree.InsertR(str,1);}else{ret->_value++;}}countTree.InOrder();}}

如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注你们的每一次支持都将转化为我前进的动力!!!

http://www.hkea.cn/news/715664/

相关文章:

  • 濮阳家电网站建设一般开车用什么导航最好
  • html5 图片展示网站大作设计网站
  • 河北正规网站建设比较百度一下你就知道官页
  • 企业网站建设哪家服务好福州网站关键词推广
  • 惠州悦商做网站软件开发一般需要多少钱
  • 做衣服外单网站优化大师官方正版下载
  • 专门做酒店的网站百度排行
  • 上海做手机网站建设盐城网站优化
  • html论坛模板东营seo整站优化
  • 天津网站建设582345网址导航桌面版
  • 东莞纸箱厂东莞网站建设经典模板网站建设
  • 贺州同城购物网站建设中国网站排名100
  • 黄骅港旅游景点爱站网seo工具包
  • 网站 图文混编提高网站搜索排名
  • 北京怀柔网站制作教育机构
  • 网站建设费 大创友链交换平台
  • o2o商城网站系统开发微信群拉人的营销方法
  • 帝国cms做淘宝客网站网页设计用什么软件
  • 营销型网站建设的优缺点视频优化软件
  • 珠海响应式网站建设推广公司网络营销发展方案策划书
  • 中国人自己的空间站每日英语新闻
  • 教师可以做网站吗seo常用工具包括
  • 武山建设局网站什么是seo
  • 做文案需要用到的网站全网模板建站系统
  • 苏州乡村旅游网站建设策划书网站建设百度推广
  • 12380网站建设情况总结百度浏览器入口
  • 直播网站开发要多久排行榜前十名
  • 网站备案完才能建站吗企业建站公司
  • 网站开发外包合同西安网站优化公司
  • 2022网页设计尺寸规范和要求怎么做seo关键词优化