二叉查找树是一种关键字有序存放的二叉树。在不含重复关键字的二叉查找树中,关键字"较小"的节点一定在关键字“较大”的节点的左子树中,“较小”一般可以由内值类型的<运算符来实现,或由重载了<运算符的类类型的<运算符来实现。“较小”的概念可以根据我们的需要有不同的实现。本文实现一个关键字类型为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. linux下查看端口对应的进程号

    在部署服务的时候,会指定对应的端口号,如果想kill 对应的端口,就要找到对应的进程,查看端口对应的进程号,有两种方法: 1.lsof命令,查看系统打开的文件(在linux中,所有的都是文件),需要管 ...

  2. 一些网络编程方面的总结,以及redis、memcache、nginx组件的一些介绍

    网络编程主要关注的一些问题 主要关注3个方面的问题 连接的建立 连接的断开 消息的发送和到达 连接的建立 主要分为两种情况:服务器处理接受客户端的连接:服务端作为客户端的连接第三方服务: //这是服务 ...

  3. 从API到Agent:万字长文洞悉LangChain工程化设计

    我想做一个尝试,看看能不能用尽量清晰的逻辑,给"AI外行人士"(当然,我也是--)引入一下LangChain,试着从工程角度去理解LangChain的设计和使用.同时大家也可以将此 ...

  4. Java浮点数内存存储

    转自: [解惑]剖析float型的内存存储和精度丢失问题 1.小数的二进制表示问题 首先我们要搞清楚下面两个问题: (1)  十进制整数如何转化为二进制数 算法很简单.举个例子,11表示成二进制数: ...

  5. mybatis 中 if else 写法

    mybaits 中没有else要用chose when otherwise 代替 <choose> <when test=""> //... </wh ...

  6. KingbaseES V8R6 备份恢复案例--异机备份ssh认证失败

    案例说明: 在生产环境,数据库服务被重启后,监控发现数据库物理备份的脚本无法执行,故障现象如下所示,从备份日志和sys_log中都出现了远程主机连接认证错误. 1)备份日志:(连接数据库服务器认证错误 ...

  7. #dp,二项式反演,容斥#CF285E Positions in Permutations

    题目 问有多少个长度为 \(n\) 的排列 \(P\) 满足 \(|P_i-i|=1\) 的 \(i\) 的个数恰好为 \(k\) 个 分析 设 \(dp_{i,j,k}\) 表示前 \(i\) 个数 ...

  8. #Kruskal,分治#AT4569 Connecting Cities

    题目传送门 考虑如何去掉这个绝对值, 换句话说,如何减少边数并且能建出 MST. 在求解偏序问题时,往往会分而治之, 这样原来 \(O(n^2)\) 的做法就能够被优化. 考虑将所有点对半折开, 左半 ...

  9. 使用OHOS SDK构建libjpeg-turbo

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/libjpeg-turb ...

  10. OpenHarmony创新赛丨报名倒计时,超强秘籍带你直通大奖!

      OpenHarmony创新赛报名倒计时开始啦! 设于开放原子全球开源大赛下的OpenHarmony创新赛,目前正在如火如荼地进行赛事招募中!这次大赛围绕创新应用.商显行业.金融行业三大赛题,邀请来 ...