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

深圳网站建设排行中央突然宣布一个大消息

深圳网站建设排行,中央突然宣布一个大消息,上海app网站建设,wordpress怎么破解付费插件一、概念与性质 二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树结构,具有以下性质: 1)若任意节点的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。 2)若任意…

一、概念与性质

二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树结构,具有以下性质:

1)若任意节点的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。

2)若任意节点的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。

3)任意节点的左子树、右子树均为二叉搜索树。

 二、二叉搜索树的特性


1. 中序遍历有序

      对 BST 进行中序遍历(左 → 根 → 右),结果是一个升序序列。
   - 示例中的树中序遍历结果:`1, 3, 4, 6, 7, 8, 10, 13, 14`

2.性能分析

最优情况下,其为完全二叉树(或者接近完全二叉树),其高度为: log 2 N
最差情况下,二叉搜索树退化为单支树(或者类似单支),如图,其高度为: N
所以综上所述,二叉搜索树增删查改时间复杂度为: O ( N )

3. 高效查找:利用有序性,每次比较可排除一半子树。


4. 动态操作:支持插入、删除、查找操作,时间复杂度与树的高度相关。

三、代码详解

1.树的创建

大致思路和我们之前创建二叉树是一样的,先造结点,之后再组装成树,只不过在这里我们没有再写一个初始化函数的必要了,因为我们可以利用c++的初始化列表在造结点的时候变完成初始化!具体代码如下:

template<class k>
struct BSTNode
{k _key;BSTNode<k>* _left;BSTNode<k>* _right;BSTNode(const k& key):_key(key),_left(nullptr),_right(nullptr){}
};template<class k>
class BSTree
{typedef BSTNode<k> Node;
public:
private:Node* _root = nullptr;
};

2.中序遍历

 这里和之前二叉树中序遍历代码基本一样,只不过我们将其进行了一下封装,详见代码注释!

void InOrder()
{_InOrder(_root);cout << endl;
}
//由于我们之后要遍历这棵树,还要传参,很麻烦,而且_root还是私有成员,我们不如在把这个函数封装一下,利于调用
void _InOrder(Node* root)
{if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);
}

3.插入功能的实现

由搜索二叉树的概念及性质我们知道,对于任意一个节点X来说,其左子树任意结点的值要小于X结点的值,其右子树任意的结点值要大于结点X,我们可以用这个性质进行插入功能的实现。具体方法如下:

1)首先确定要在什么位置插入,由于这是树状结构,如果我们只用一个指针的话即便找到位置也无法插入,因为指针不能倒着走回去,所以在这里我们可以借用之前的双指针法,依次定位追踪父节点和子节点,在结合上文所说的,大于当前结点向右看,小于向左看,从而确定插入的位置 

2)找到插入的位置之后,直接将要插入的数据打包成结点,并根据BSTree的性质,判断插在左子树还是右子树

注:插入值跟当前结点相等的值,可以往右走,也可以往左走,找到空位置,插入新结点。

(要注意的是要保持逻辑一致性,插入相等的值不要一会往右走,一会往左走)

代码实现如下:

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这个位置插入结点cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;
}

 测试一下:

void test1()
{int a[]= { 8, 3, 1, 10, 1, 6, 4, 7, 14, 13 };BSTree<int> bst;for (auto e : a){bst.Insert(e);}bst.InOrder();
}
int main()
{test1();     //输出1 3 4 6 7 8 10 13 14return 0;
}

4.查找功能的实现

查找功能的代码较为简单,利用BStree的性质遍历即可,代码如下:

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

5.删除功能的实现

要删除的结点X分为如下几种情况:

1)X的左右孩子均为空

2)X的左右孩子中有一个为空

3)X的左右孩子均不为空

解决方法如下:首先找到要删除的结点,

若为第一种情况,则直接删除

若为第二种情况,下一步要判断结点X是左孩子还是右孩子,并将X的父节点与X的子节点链接起来

若为第三种情况, 由于直接删的代价太大,我们还是借助堆的删除的方法,交换法,找左子树的最大结点(最右结点)或者右子树的最小结点(最左结点),将二者交换,之后准备删除工作,首先要判断的是X结点在其父节点的哪一侧,(具体原因详见代码)之后删除结点,并将其父节点与X的子节点连接起来即可

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;}else{if (cur == parent->_right){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 找右子树的最小节点(最左节点)替代Node* replaceparnet = cur;Node* replace = cur->_right;//找最左节点while (replace->_left){replaceparnet = replace;replace = replace->_left;}swap(cur->_key, replace->_key);//此时还要判断一下replace在哪一侧,因为假如replace在右,而parent还有左孩子//此时直接改会导致原来的子树失联if (replaceparnet->_left == replace){//由于此时replace已经是最左结点(其没有左孩子了,但是右孩子不确定),// 所以parent的左孩子和replace的右孩子建立关系replaceparnet->_left = replace->_right;}else{//解释同上,确定好左右关系即可replaceparnet->_right = replace->_right;}delete replace;}return true;}}return false;
}

6.总体代码汇总

 这是bstree.h文件

#pragma once
#include<iostream>
using namespace std;
template<class k>
struct BSTNode
{k _key;BSTNode<k>* _left;BSTNode<k>* _right;BSTNode(const k& key):_key(key),_left(nullptr),_right(nullptr){}
};template<class k>
class BSTree
{typedef BSTNode<k> Node;
public: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这个位置插入结点cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}void InOrder(){_InOrder(_root);cout << endl;}//由于我们之后要遍历这棵树,还要传参,而且_root还是私有成员,我们不如在把这个函数封装一下void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}void Find(const k& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}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;}else{if (cur == parent->_right){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 找右子树的最小节点(最左节点)替代Node* replaceparnet = cur;Node* replace = cur->_right;//找最左节点while (replace->_left){replaceparnet = replace;replace = replace->_left;}swap(cur->_key, replace->_key);//此时还要判断一下replace在哪一侧,因为假如replace在右,而parent还有左孩子//此时直接改会导致原来的子树失联if (replaceparnet->_left == replace){//由于此时replace已经是最左结点(其没有左孩子了,但是右孩子不确定),// 所以parent的左孩子和replace的右孩子建立关系replaceparnet->_left = replace->_right;}else{//解释同上,确定好左右关系即可replaceparnet->_right = replace->_right;}delete replace;}return true;}}return false;}private:Node* _root = nullptr;
};

这是Test.cpp文件

#include "bstree.h"
void test1()
{int a[]= { 8, 3, 1, 10, 1, 6, 4, 7, 14, 13 };BSTree<int> bst;for (auto e : a){bst.Insert(e);}bst.InOrder();bst.Insert(18);bst.InOrder();bst.Insert(5);bst.InOrder();bst.Insert(0);bst.InOrder();bst.Erase(18);bst.InOrder();bst.Erase(0);bst.InOrder();bst.Erase(5);bst.InOrder();for (auto e : a){bst.Erase(e);bst.InOrder();}
}
int main()
{test1();     return 0;
}

7.扩展

在现实中,我们可能很少遇到结点变量只有一个的情况,比如我们想做一个英汉搜索字典,或者统计一下某个单词或字符出现了多少次,那我们便可以加一个模板参数,具体见代码!

这是.h文件

namespace key_value
{template<class k,class v>struct BSTNode{k _key;v _value;BSTNode<k,v>* _left;BSTNode<k,v>* _right;BSTNode(const k& key,const v& value):_key(key),_value(value), _left(nullptr), _right(nullptr){}};template<class k,class v>class BSTree{typedef BSTNode<k,v> Node;public:~BSTree(){Destory(_root);_root = nullptr;}bool Insert(const k& key,const v& value){if (_root == nullptr){_root = new Node(key,value);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这个位置插入结点cur = new Node(key,value);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}void InOrder(){_InOrder(_root);cout << endl;}//由于我们之后要遍历这棵树,还要传参,而且_root还是私有成员,我们不如在把这个函数封装一下void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " " << root->_value << endl;_InOrder(root->_right);}Node* Find(const k& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return cur;}}return nullptr;}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;}else{if (cur == parent->_right){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 找右子树的最小节点(最左节点)替代Node* replaceparnet = cur;Node* replace = cur->_right;//找最左节点while (replace->_left){replaceparnet = replace;replace = replace->_left;}swap(cur->_key, replace->_key);swap(cur->_value, replace->_key);//此时还要判断一下replace在哪一侧,因为假如replace在右,而parent还有左孩子//此时直接改会导致原来的子树失联if (replaceparnet->_left == replace){//由于此时replace已经是最左结点(其没有左孩子了,但是右孩子不确定),// 所以parent的左孩子和replace的右孩子建立关系replaceparnet->_left = replace->_right;}else{//解释同上,确定好左右关系即可replaceparnet->_right = replace->_right;}delete replace;}return true;}}return false;}void Destory(Node* root){if (root == nullptr){return;}Destory(root->_left);Destory(root->_right);delete root;}private:Node* _root = nullptr;};
}

 这是英汉词典和统计次数的示例

void test2()
{using namespace key_value;key_value::BSTree<string, string> dict;dict.Insert("left", "左边");dict.Insert("right", "右边");dict.Insert("insert", "插入");dict.Insert("string", "字符串");//查字典string str;while (cin >> str){auto ret = dict.Find(str);if (ret){cout << "->" << ret->_value << endl;}else{cout << "无此单词,请重新输入" << endl;}}//数水果string arr[] = { "苹果", "西瓜", "苹果","苹果","苹果", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };key_value::BSTree<string, int> countTree;for (auto& e : arr){BSTNode<string, int>* ret = countTree.Find(e);if (ret == nullptr){countTree.Insert(e, 1);}else{ret->_value++;}}countTree.InOrder();}

这是测试结果

http://www.dtcms.com/wzjs/498714.html

相关文章:

  • 廉政网站管理制度建设宁德市古田县
  • 自己做家具的网站口碑营销策略有哪些
  • 拓者设计吧官网效果图廊坊seo排名公司
  • 用wordpress做的外贸网站app拉新接单平台
  • 浙江省住房建设局网站首页站长查询域名
  • 建立自己的网站可以采用的方式有地推平台去哪里找
  • 电子商务网站建设 市场分析营销技巧
  • 有哪些做平面设计好素材网站优化网站
  • 理财网站如何做推广方案优势的seo网站优化排名
  • 淄川政府网站建设托管网络营销sem培训
  • 做实体上什么网站找项目天津seo
  • 新手怎么做网站打理企业培训课程开发
  • 网站banner的js特效怎么做网站开发需要哪些技术
  • 网站建设兼职挣多少钱免费网站
  • 二手书屋网站开发的意义南宁seo营销推广
  • 网站建设公司ttmwl福州seo推广公司
  • 上街三屏网站建设抖音搜索seo软件
  • 青岛知名网站建设公司排名微信朋友圈广告投放收费标准
  • 天津网站seo服务巩义网站推广优化
  • 怎么用vs2017做网站电脑系统优化软件排行榜
  • 杭州建设教育网站巩义网络推广外包
  • 网站建设小程序开发报价百度搜索引擎排名规则
  • 东莞凤岗做网站如何软件网站优化公司
  • 做酒的网站名字大全企业网站有哪些
  • 网页设计制作个人网站搜索引擎和浏览器
  • 赤峰网站建设red短视频营销成功案例
  • 做网站插入文档特殊字符强强seo博客
  • 做网站怎样赚到钱百度账号怎么改用户名
  • 做网站需要的语言湖南seo优化服务
  • 龙岩做网站改版找哪家公司网站搜索引擎优化技术