需要注意的地方:

①二叉搜索树删除一个指定结点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++实现二叉搜索树的数据结构的更多相关文章

  1. hdu 3791:二叉搜索树(数据结构,二叉搜索树 BST)

    二叉搜索树 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submiss ...

  2. c++实现二叉搜索树

    自己实现了一下二叉搜索树的数据结构.记录一下: #include <iostream> using namespace std; struct TreeNode{ int val; Tre ...

  3. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  4. 【算法与数据结构】二叉搜索树的Java实现

    为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指 ...

  5. 数据结构之二叉搜索树、AVL自平衡树

    前言 最近在帮公司校招~~ 所以来整理一些数据结构方面的知识,这些知识呢,光看一遍理解还是很浅的,看过跟动手做过一遍的同学还是很容易分辨的哟~ 一直觉得数据结构跟算法,就好比金庸小说里的<九阳神 ...

  6. 自己动手实现java数据结构(六)二叉搜索树

    1.二叉搜索树介绍 前面我们已经介绍过了向量和链表.有序向量可以以二分查找的方式高效的查找特定元素,而缺点是插入删除的效率较低(需要整体移动内部元素):链表的优点在于插入,删除元素时效率较高,但由于不 ...

  7. 用Python实现数据结构之二叉搜索树

    二叉搜索树 二叉搜索树是一种特殊的二叉树,它的特点是: 对于任意一个节点p,存储在p的左子树的中的所有节点中的值都小于p中的值 对于任意一个节点p,存储在p的右子树的中的所有节点中的值都大于p中的值 ...

  8. 【Java】 大话数据结构(11) 查找算法(2)(二叉排序树/二叉搜索树)

    本文根据<大话数据结构>一书,实现了Java版的二叉排序树/二叉搜索树. 二叉排序树介绍 在上篇博客中,顺序表的插入和删除效率还可以,但查找效率很低:而有序线性表中,可以使用折半.插值.斐 ...

  9. 数据结构-二叉搜索树(BST binary search tree)

    本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 二叉搜索树简介 顾名思义,二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以用一个链表数据结构来 ...

随机推荐

  1. LockSupport HotSpot里park/unpark的实现

    每个java线程都有一个Parker实例,Parker类是这样定义的: class Parker : public os::PlatformParker { private: volatile int ...

  2. How To Mine Bitcoins 比特币挖矿

    linux 下查看 gpu 的信息: sudo lshw -C display windows下查看cuda信息:In directory C:\Program Files\NVIDIA Corpor ...

  3. Centos7 Zabbix3.2安装

    实验环境: 阿里云 [zabbix@miyan ~]$ cat /etc/redhat-release CentOS Linux release (Core) 不得不说,官方文档确实强大 1.官方文档 ...

  4. layer官方演示与讲解(jQuery弹出层插件)

    1. 使用layer遇到困难?Fly社区虔诚为您解惑 2. layer 2.0 发布,以独立形式呈现的最后一个版本 3. Fork layer on Github,爱她,就给她加个星啵 当前版本:2. ...

  5. ZOHO 免费小型企业邮箱和个人邮箱

    Zoho Mail 提供免费小型企业邮箱注册.精简版只能添加一个域到您的机构帐号,最多允许10用户.如果您想添加多个域,您可以升级到标准版.10用户免费,5 GB /每用户,5 GB (共享). 除了 ...

  6. tp模板基础

    目录简介 创建应用 在项目目录创建入口文件shop/index.php 创建虚拟主机,访问应 路由形式 路由: 系统从URL参数中分析出当前请求的分组.控制器.和操作的过程就是“路由”. Tp框架路由 ...

  7. 线程、进程、daemon、GIL锁、线程锁、递归锁、信号量、计时器、事件、队列、多进程

    # 本文代码基于Python3 什么是进程? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行 ...

  8. JavaScript实现Map功能

    JavaScript中没有类似Java中的Map集合类的实现,自己做了简单实现,如下: function Map() { this.elements = new Array(); this.size= ...

  9. centOS下升级python版本,详细步骤

    1.可利用linux自带下载工具wget下载,如下所示:(  笔者安装的是最小centos系统,所以使用编译命令前,必须安装wget服务,读者如果安装的是界面centos系统,或者使用过编译工具则可跳 ...

  10. vs+qt使用资源文件

    1.在Resources目录新建一个.qrc文件 2.在解决方案的Resource Files中添加这个文件 3.为这个qrc添加资源,建议把资源都放进Resources