使用C++实现二叉搜索树的数据结构
需要注意的地方:
①二叉搜索树删除一个指定结点R,若R为叶子结点,则将R的父结点中指向R的指针改为指向nullptr;若R的左右子结点一个为空,一个非空,则将R的父结点中指向R的指针改为指向R的非空子结点;若R有两个非空子结点,则找出R的右子树中的最小值结点,将其删除并将R的值置为该最小值结点的值。
②对二叉搜索树进行中序遍历,将得到按升序排序的输出结果。
③使用了多态,二叉搜索树结点类BSTNode继承自抽象类BinNode(二叉树结点类)。
④二叉搜索树不是自平衡的,二叉搜索树的平衡性取决于结点的插入顺序,在极端情况二叉搜索树会退化成链表,查找元素的时间复杂度会退化为O(N)。
代码如下,写在头文件中:
#ifndef BST_H
#define BST_H #include <iostream>
#include <queue> /************************************************************************/
/* 抽象二叉树结点类 */
/************************************************************************/
template <typename Val>
class BinNode
{
public:
virtual ~BinNode() {}
virtual bool IsLeaf() const = ;
virtual Val GetValue() const = ;
virtual void SetValue(const Val &val_) = ;
virtual BinNode* GetLeftChild() const = ;
virtual void SetLeftChild(BinNode *lc) = ;
virtual BinNode* GetRightChild() const = ;
virtual void SetRightChild(BinNode *rc) = ;
virtual void InOrderTraverse() const = ;
}; /************************************************************************/
/* 二叉搜索树结点类 */
/************************************************************************/
template <typename Key, typename Val>
class BSTNode : public BinNode<Val>
{
public:
BSTNode()
: key(), val(), left_(nullptr), right_(nullptr) {}
BSTNode(const Key &key_, const Val &val_, BSTNode *lc = nullptr, BSTNode *rc = nullptr)
: key(key_), val(val_), left_(lc), right_(rc) {}
~BSTNode() {}
bool IsLeaf() const { return (left_ == nullptr) && (right_ == nullptr); } //判断是否为叶结点
Key GetKey() const { return key; }
void SetKey(const Key &key_) { key = key_; } //删除结点时用到,其他情况下不可对key值做修改
Val GetValue() const { return val; }
void SetValue(const Val &val_) { val = val_; }
BSTNode* GetLeftChild() const { return left_; }
void SetLeftChild(BinNode<Val> *lc) { left_ = dynamic_cast<BSTNode*>(lc); }
BSTNode* GetRightChild() const { return right_; }
void SetRightChild(BinNode<Val> *rc) { right_ = dynamic_cast<BSTNode*>(rc); }
void InOrderTraverse() const; //中序遍历
private:
Key key;
Val val;
BSTNode *left_;
BSTNode *right_;
}; template <typename Key, typename Val>
void BSTNode<Key, Val>::InOrderTraverse() const
{
if (left_ != nullptr)
{
left_->InOrderTraverse();
}
std::cout << "Key: " << key << ", Value: " << val << "\n";
if (right_ != nullptr)
{
right_->InOrderTraverse();
}
} /************************************************************************/
/* 二叉搜索树类 */
/************************************************************************/
template <typename Key, typename Val>
class BSTree
{
public:
BSTree()
: root(nullptr), node_num() {}
~BSTree() { Deconstructor(root); }
BSTree(const BSTree &bst) = delete; //禁止编译器生成拷贝构造函数
BSTree& operator=(const BSTree &bst) = delete; //禁止编译器重载拷贝赋值运算符
void InOrderTraverse() const; //中序遍历
void Insert(const Key &key, const Val &val); //插入新结点
Val Delete(const Key &key); //删除指定结点,返回结点的值
Val Find(const Key &key) const; //获取指定key值结点对应的val值
void SetEmpty(); //清空树中所有结点
void BFS() const; //广度优先搜索遍历
unsigned int Size() const { return node_num; }
private:
BSTNode<Key, Val> *root;
unsigned int node_num;
/************************************************************************/
/* 私有函数 */
/************************************************************************/
BSTNode<Key, Val>* Inserter(BSTNode<Key, Val> *root, const Key &key, const Val &val); //插入结点的辅助函数
void Deconstructor(BSTNode<Key, Val> *root); //析构函数的辅助函数,delete所有结点
BSTNode<Key, Val>* GetMinValueNode(BSTNode<Key, Val> *root) const; //找到Key值最小的结点
BSTNode<Key, Val>* DeleteMinValueNode(BSTNode<Key, Val> *root); //删除Key值最小的结点
BSTNode<Key, Val>* Deleter(BSTNode<Key, Val> *root, const Key &key); //删除结点的辅助函数
Val Finder(BSTNode<Key, Val> *root, const Key &key) const; //找出指定Key值的结点,并返回val的值
}; template <typename Key, typename Val>
void BSTree<Key, Val>::InOrderTraverse() const
{
if (root == nullptr)
{
return;
}
std::cout << "Inorder Traverse:\n";
root->InOrderTraverse();
} template <typename Key, typename Val>
void BSTree<Key, Val>::Insert(const Key &key, const Val &val)
{
root = Inserter(root, key, val);
++node_num;
} template <typename Key, typename Val>
BSTNode<Key, Val>* BSTree<Key, Val>::Inserter(BSTNode<Key, Val> *root, const Key &key, const Val &val)
{
if (root == nullptr)
{
return new BSTNode<Key, Val>(key, val, nullptr, nullptr);
}
if (key < root->GetKey())
{
root->SetLeftChild(Inserter(root->GetLeftChild(), key, val));
}
else
{
root->SetRightChild(Inserter(root->GetRightChild(), key, val));
}
return root;
} template <typename Key, typename Val>
void BSTree<Key, Val>::Deconstructor(BSTNode<Key, Val> *root)
{
if (root == nullptr)
{
return;
}
Deconstructor(root->GetLeftChild());
Deconstructor(root->GetRightChild());
delete root;
} template <typename Key, typename Val>
BSTNode<Key, Val>* BSTree<Key, Val>::GetMinValueNode(BSTNode<Key, Val> *root) const
{
if (root->GetLeftChild() == nullptr)
{
return root;
}
else
{
return GetMinValueNode(root->GetLeftChild());
}
} template <typename Key, typename Val>
BSTNode<Key, Val>* BSTree<Key, Val>::DeleteMinValueNode(BSTNode<Key, Val> *root)
{
if (root->GetLeftChild() == nullptr)
{
return root->GetRightChild();
}
else
{
root->SetLeftChild(DeleteMinValueNode(root->GetLeftChild()));
return root;
}
} template <typename Key, typename Val>
Val BSTree<Key, Val>::Delete(const Key &key)
{
Val temp_val = Finder(root, key);
if (temp_val != Val())
{
root = Deleter(root, key);
--node_num;
}
return temp_val;
} template <typename Key, typename Val>
BSTNode<Key, Val>* BSTree<Key, Val>::Deleter(BSTNode<Key, Val> *root, const Key &key)
{
if (root == nullptr)
return nullptr;
if (key < root->GetKey())
{
root->SetLeftChild(Deleter(root->GetLeftChild(), key));
}
else if (key > root->GetKey())
{
root->SetRightChild(Deleter(root->GetRightChild(), key));
}
else
{
if (root->GetLeftChild() == nullptr)
{
BSTNode<Key, Val> *temp_node = root;
root = root->GetRightChild();
delete temp_node;
}
else if (root->GetRightChild() == nullptr)
{
BSTNode<Key, Val> *temp_node = root;
root = root->GetLeftChild();
delete temp_node;
}
else
{
BSTNode<Key, Val> *temp_node = GetMinValueNode(root->GetRightChild());
root->SetValue(temp_node->GetValue());
root->SetKey(temp_node->GetKey());
root->SetRightChild(DeleteMinValueNode(root->GetRightChild()));
delete temp_node;
}
}
return root;
} template <typename Key, typename Val>
Val BSTree<Key, Val>::Find(const Key &key) const
{
return Finder(root, key);
} template <typename Key, typename Val>
Val BSTree<Key, Val>::Finder(BSTNode<Key, Val> *root, const Key &key) const
{
if (root == nullptr)
{
return Val(); //对应的结点不存在,返回Val类型的默认值
}
if (key < root->GetKey())
{
return Finder(root->GetLeftChild(), key);
}
else if (key > root->GetKey())
{
return Finder(root->GetRightChild(), key);
}
else
{
return root->GetValue();
}
} template <typename Key, typename Val>
void BSTree<Key, Val>::SetEmpty()
{
Deconstructor(root);
root = nullptr;
node_num = ;
} template <typename Key, typename Val>
void BSTree<Key, Val>::BFS() const
{
std::queue<BSTNode<Key, Val>*> node_queue;
node_queue.push(root);
BSTNode<Key, Val> *temp_node = nullptr;
std::cout << "Breadth First Search Traverse:\n";
while (!node_queue.empty())
{
temp_node = node_queue.front();
node_queue.pop();
std::cout << "Key: " << temp_node->GetKey() << ", Value: " << temp_node->GetValue() << "\n";
if (temp_node->GetLeftChild() != nullptr)
{
node_queue.push(temp_node->GetLeftChild());
}
if (temp_node->GetRightChild() != nullptr)
{
node_queue.push(temp_node->GetRightChild());
}
}
} #endif
使用C++实现二叉搜索树的数据结构的更多相关文章
- hdu 3791:二叉搜索树(数据结构,二叉搜索树 BST)
二叉搜索树 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submiss ...
- c++实现二叉搜索树
自己实现了一下二叉搜索树的数据结构.记录一下: #include <iostream> using namespace std; struct TreeNode{ int val; Tre ...
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- 【算法与数据结构】二叉搜索树的Java实现
为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指 ...
- 数据结构之二叉搜索树、AVL自平衡树
前言 最近在帮公司校招~~ 所以来整理一些数据结构方面的知识,这些知识呢,光看一遍理解还是很浅的,看过跟动手做过一遍的同学还是很容易分辨的哟~ 一直觉得数据结构跟算法,就好比金庸小说里的<九阳神 ...
- 自己动手实现java数据结构(六)二叉搜索树
1.二叉搜索树介绍 前面我们已经介绍过了向量和链表.有序向量可以以二分查找的方式高效的查找特定元素,而缺点是插入删除的效率较低(需要整体移动内部元素):链表的优点在于插入,删除元素时效率较高,但由于不 ...
- 用Python实现数据结构之二叉搜索树
二叉搜索树 二叉搜索树是一种特殊的二叉树,它的特点是: 对于任意一个节点p,存储在p的左子树的中的所有节点中的值都小于p中的值 对于任意一个节点p,存储在p的右子树的中的所有节点中的值都大于p中的值 ...
- 【Java】 大话数据结构(11) 查找算法(2)(二叉排序树/二叉搜索树)
本文根据<大话数据结构>一书,实现了Java版的二叉排序树/二叉搜索树. 二叉排序树介绍 在上篇博客中,顺序表的插入和删除效率还可以,但查找效率很低:而有序线性表中,可以使用折半.插值.斐 ...
- 数据结构-二叉搜索树(BST binary search tree)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 二叉搜索树简介 顾名思义,二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以用一个链表数据结构来 ...
随机推荐
- 驼峰命名和下划线命名互转php实现
驼峰命名和下划线命名经常需要互转,下面提供两种php的实现方式.第一种方法效率相对差一些,实现方式如下: //驼峰命名转下划线命名 function toUnderScore($str) { $dst ...
- mysql++使用
Mysql++是官方发布的.一个为MySQL设计的C++语言的API.Mysql++为Mysql的C-Api的再次封装,它用STL(Standard Template Language)开发并编写,并 ...
- keras实现不同形态的模型
keras提供了Sequential线性的模型,但是有些网络需要多个输入,有些网络有多个输出,更甚之层与层之间有内部分支,这使得网络看起来像是层构成的图,而不是线性的堆叠.有些场景需要多模态的输入,这 ...
- 4.8 Routing -- Specifying The URL Type
1. 默认的路由器使用浏览器的hash来加载应用程序的开始状态并且当你移动时同步保持.目前,这依赖于浏览器中存在的hashchange事件. 2. 假设下面的路由器,输入/#/posts/new将会把 ...
- 小论“Boolean参数作为入参”的函数
<Clean Code>一书中对于如何写好函数有着很动人的描写,其中对于函数参数的建议有如下两点: 函数参数的数量应该尽可能少 给一个一元函数传入bool类型的参数很"罪恶&qu ...
- TFS2015源代码管理器无法建立团队项目的问题
最近在服务器安装了微软最新版的TFS2015 正版要钱,网络上还没有能找到可用的key,因此我只能使用试用版. 安装完成后,使用我本地的vs2013 vs2012 vs2010 vs2014 ...
- 线程、进程、daemon、GIL锁、线程锁、递归锁、信号量、计时器、事件、队列、多进程
# 本文代码基于Python3 什么是进程? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行 ...
- iOS重签名脚本
unzip xxx.ipa //解压ipa rm -rf Payload/ xxx.app/_CodeSignature //删除旧签名 cp newEmbedded.mobileprovision ...
- Mybatis-plus之RowBounds实现分页查询
物理分页和逻辑分页 物理分页:直接从数据库中拿出我们需要的数据,例如在Mysql中使用limit. 逻辑分页:从数据库中拿出所有符合要求的数据,然后再从这些数据中拿到我们需要的分页数据. 优缺点 物理 ...
- cookie注入原理详解(一)
那我们还是围绕以下几个问题来看看cookie注入: 1.什么是cookie注入? 2.为什么要cookie注入? 3.怎样cookie注入? 1.什么是cookie注入? ♦cookie注入的原理是: ...