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

在韶关做网站seo二级目录

在韶关做网站,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.zhongyajixie.com/news/4464.html

相关文章:

  • 朝阳区手机网站制作服务谷歌地图下载
  • 镇海区住房建设网站怎么查seo企业站收录
  • 系统优化有什么用北京网站seowyhseo
  • 美国做3d h动画的网站播放量自助下单平台
  • 域名的网站建设方案书怎么写一键开发小程序
  • 微商网站怎么做的丽水网站seo
  • 电子商务网站建设期末考试成都新站软件快速排名
  • 网站建设综合设计google下载
  • 青岛网站开发培训价格传统营销与网络营销的区别
  • 网站建设代理商福州seo服务
  • 本溪做网站的搜索引擎seo如何赚钱
  • 徐州沛县网站建设网站推广平台有哪些
  • 湘潭做网站的公司合肥seo代理商
  • 电子书网站搭建教程淘词神器
  • 深圳外贸soho网站建设营销比较好的知名公司有哪些
  • 赣县网站制作海南seo快速排名优化多少钱
  • 网站建设 .北京蓝纤如何让产品吸引顾客
  • 音乐网站怎么做无线增值业务seo公司关键词
  • 重庆专业网站开发服务什么软件可以排名次
  • 门户网站大全网站seo诊断分析
  • 网站建设徐州网络推广软文范文
  • 建平台网站百度搜索引擎入口登录
  • 做网站的积木式编程推广软件有哪些
  • 汽车可以做哪些广告视频网站有哪些网络推广具体内容
  • 新疆维吾尔自治区官网百度seo站长工具
  • 怎样设计网站主页军事新闻头条最新消息
  • wordpress 内链网站优化设计公司
  • 做定制网站多少钱网店推广的作用是什么
  • 网络规划与设计思维导图seo培训学院
  • 苏州有哪些做网站关键词全网搜索