二叉查找树是一种关键字有序存放的二叉树。在不含重复关键字的二叉查找树中,关键字"较小"的节点一定在关键字“较大”的节点的左子树中,“较小”一般可以由内值类型的<运算符来实现,或由重载了<运算符的类类型的<运算符来实现。“较小”的概念可以根据我们的需要有不同的实现。本文实现一个关键字类型为elemType的二叉查找树,elemType可以是内置类型,也可以是自定义类型,如果是自定义类型,二叉查找树要求类型实现一些比较运算符,能够定义"较大"、“较小”、”相等“、”不等“这些概念。

本文实现操作:

1. 层序遍历  2. 插入  3.删除

4.查找     5. 根据若干给定元素建树

0. 二叉查找树的定义

//binary tree
struct binTree
{
elemType data;  
binTree* lchild;
binTree* rchild;
binTree(elemType data):data(data),lchild(NULL),rchild(NULL) {};
};

1. 层序遍历

这里使用队列来实现层序遍历。并接受一个void (*) (const binTree* root) 类型的函数指针作为参数,定义遍历节点时要对节点进行的操作。

//层序遍历,对每一个节点执行函数指针pfun指定的操作
void layerOrderTravel(const binTree * root,void (*pfun) (const binTree* root) )
{
if( root == NULL ) return ;
std::queue<const binTree*> q;
q.push(root);
while(!q.empty())
{
const binTree* node = q.front();
if( node->lchild != NULL ) q.push(node->lchild);
if( node->rchild != NULL ) q.push(node->rchild);
pfun(node);
q.pop();
}
return ;
}

2. 插入

//在根为root的二叉查找树树中插入元素为x的节点
void BSTInsert(binTree*& root,elemType x)
{
//root==NULL即找到了插入位置
if( root == NULL )
{
root = new binTree(x);
//cout << "正在插入" << x << endl;
return ;
}
//对于不允许重复元素的树,若x已存在,直接返回。
if( root->data == x ) return ;
//在左子树中插入
if( x < root->data )
BSTInsert(root->lchild,x);
//在右子树中插入
if( x > root->data )
BSTInsert(root->rchild,x);
}

3. 删除

//在root中删除值为x的节点
void BSTDelete(binTree*& root,elemType x)
{
//
if( root == NULL ) return ;
//找到了要删除的节点
if( root->data == x )
{
if( root->lchild == NULL && root->rchild == NULL )
{
//节点没有左右孩子,直接将该节点指针置空,其父节点中指向这个节点的lchild或rchild会相应地指向NULL
root = NULL;
return ;
}
//如果有左孩子,令其直接前驱代替其值,并递归地在左子树中删除其直接前驱
else if( root->lchild != NULL )
{
binTree* node = root->lchild;
while( node->rchild )
node = node->rchild;
root->data = node->data;
BSTDelete(root->lchild,node->data);
}
else if( root->rchild != NULL )
{
binTree* node = root->rchild;
while( node->lchild )
node = node->lchild;
root->data = node->data;
BSTDelete(root->rchild,node->data);
}
}
else if( x < root->data ) BSTDelete(root->lchild,x);
else if( x > root->data ) BSTDelete(root->rchild,x);
}

4. 查找

//在根为root的树中查找值为x的节点
binTree* BSTFind( binTree* root,elemType x)
{
if( root == NULL )
{
std::cout << "空树" << std::endl;
//throw
return NULL;
}
//找到了
if( root->data == x )
return root;
//在右子树中查找
if( root->data < x )
return BSTFind(root->rchild,x);
//在左子树中查找
if( root->data > x )
return BSTFind(root->lchild,x); //throw
return NULL;
}

5. 建树

//由给定的元素序列elems创建一棵二叉查找树,返回树根节点的指针
binTree* createBST(const std::vector<elemType>& elems)
{
binTree* root = NULL;
for( std::vector<elemType>::const_iterator it = elems.begin(); it != elems.end(); ++it )
{
BSTInsert(root,*it);
}
return root;
}

二叉查找树的实现C/C++的更多相关文章

  1. 数据结构:二叉查找树(C语言实现)

    数据结构:二叉查找树(C语言实现) ►写在前面 关于二叉树的基础知识,请看我的一篇博客:二叉树的链式存储 说明: 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 1.若其左子树不空,则左子树上 ...

  2. 数据结构笔记--二叉查找树概述以及java代码实现

    一些概念: 二叉查找树的重要性质:对于树中的每一个节点X,它的左子树任一节点的值均小于X,右子树上任意节点的值均大于X. 二叉查找树是java的TreeSet和TreeMap类实现的基础. 由于树的递 ...

  3. codevs 1285 二叉查找树STL基本用法

    C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...

  4. 平衡二叉查找树(AVL)的理解与实现

    AVL树的介绍 平衡二叉树,又称AVL(Adelson-Velskii和Landis)树,是带有平衡条件的二叉查找树.这个平衡条件必须要容易保持,而且它必须保证树的深度是 O(log N).一棵AVL ...

  5. 二叉查找树 C++实现(含完整代码)

    一般二叉树的查找是通过遍历整棵二叉树实现,效率较低.二叉查找树是一种特殊的二叉树,可以提高查找的效率.二叉查找树又称为二叉排序树或二叉搜索树. 二叉查找树的定义 二叉排序树(Binary Search ...

  6. 数据结构——二叉查找树、AVL树

    二叉查找树:由于二叉查找树建树的过程即为插入的过程,所以其中序遍历一定为升序排列! 插入:直接插入,插入后一定为根节点 查找:直接查找 删除:叶子节点直接删除,有一个孩子的节点删除后将孩子节点接入到父 ...

  7. Java for LintCode 验证二叉查找树

    给定一个二叉树,判断它是否是合法的二叉查找树(BST) 一棵BST定义为: 节点的左子树中的值要严格小于该节点的值.    节点的右子树中的值要严格大于该节点的值.    左右子树也必须是二叉查找树. ...

  8. 数据结构和算法 – 9.二叉树和二叉查找树

      9.1.树的定义   9.2.二叉树 人们把每个节点最多拥有不超过两个子节点的树定义为二叉树.由于限制子节点的数量为 2,人们可以为插入数据.删除数据.以及在二叉树中查找数据编写有效的程序了. 在 ...

  9. 二叉树-二叉查找树-AVL树-遍历

    一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...

  10. 二叉查找树的Java实现

    为了克服对树结构编程的恐惧感,决心自己实现一遍二叉查找树,以便掌握关于树结构编程的一些技巧和方法.以下是基本思路: [1] 关于容器与封装.封装,是一种非常重要的系统设计思想:无论是面向过程的函数,还 ...

随机推荐

  1. 痞子衡嵌入式:使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤. 在痞子衡旧文 <在i.MXRT1170上快速点亮一款全新LCD ...

  2. Mysql中数据类型括号中的数字代表的含义

    相信大家不管是看别人的代码,还是自己的代码总会在定义表的数据类型时,会需要在数据类型后面加一个括号,里面写一个参数,例如int(3),smallint(5),char(5)等,但是括号里面的数字到底是 ...

  3. MySQL系列:索引失效场景总结

    相关文章 数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩 ...

  4. 从零开始写 Docker(七)---实现 mydocker commit 打包容器成镜像

    本文为从零开始写 Docker 系列第七篇,实现类似 docker commit 的功能,把运行状态的容器存储成镜像保存下来. 完整代码见:https://github.com/lixd/mydock ...

  5. Python实现简易版TCP代理

    什么是TCP代理 TCP代理是一种网络代理技术,它允许客户端和服务器之间通过一个位于中间的第三方TCP代理服务器进行通信.TCP代理的工作方式是客户端向代理服务器发送TCP连接请求,代理服务器将此请求 ...

  6. TP6框架--EasyAdmin学习笔记:定义路由

    这是我写的学习EasyAdmin的第二章,这一章我给大家分享下如何定义一条路由 正常的tp6定义路由方法如下: /route/admins/app.php 文件内容 //路由变量自定义 Route:: ...

  7. java 获取文件MD5值

    private final char[] hexCode = "0123456789ABCDEF".toCharArray(); public String toHexString ...

  8. LCD - 液晶显示原理(一)

    1. 显示器介绍 ​ 显示器属于计算机的I/O设备,即输入输出设备.它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具.常见的有CRT显示器.液晶显示器. LED点阵显示器及OLED显示器. 液 ...

  9. Spring Bean 的一生

    Spring Bean 的一生包括其从创建到消亡的整个过程: 实例创建 => 填充 => 初始化 => 使用 => 销毁. 这里需要注意的是,从 bean 实例的创建到可以使用 ...

  10. defer 延迟调用【GO 基础】

    〇.前言 在 Go 语言中,defer 是一种用于延迟调用的关键字. defer 在 Go 语言中的地位非常重要,它是确保资源正确释放和程序健壮性的关键字. 本文将通过示例对其进行专门的详解. 一.d ...