什么是二叉搜索树

二叉搜索树(binary search tree,BST[1])也叫排序的二叉树,根节点比左边子树的所有节点都大,比右边子树上的所有节点都小,如下图就是一个二叉搜索树:

要实现一个二叉搜索树, 我们需要实现节点的插入和删除,要实现节点的查找(搜索),要实现前序遍历、中序遍历和后序遍历,要实现最大节点和最小节点的查找。

下面就让我们实现这个二叉搜索树。

定义基本数据结构

常规地,我们定义节点的类型,每个节点包含它的值以及左右节点。因为目前 Go 泛型还没有发布,所以这里我们实现一个元素为 int 类型的具体的二叉搜索树,等泛型实现后可以改成抽象的二叉搜索树。

树只要包含根节点可以了。

// Node 定义节点.

type Node struct {

value int // 因为目前Go的泛型还没有发布,所以我们这里以一个int具体类型为例

left *Node // 左子节点

right *Node // 右子节点

}

// BST 是一个节点的值为int类型的二叉搜索树.

type BST struct {

root *Node

}

数据结构有了,接下来就是实现各个方法。

插入和删除

既然是一棵树,就需要增加节点用来构造树,大部分情况下也需要删除节点。

增加节点的时候,需要判断应该往左边子树上添加,还是往右边子树上添加。天然地,既然二叉搜索树是一个有序的,那么我们就可以进行比较,然后递归的实现。

// Insert 插入一个元素.

func (bst *BST) Insert(value int) {

newNode := &Node{value, nil, nil}

// 如果二叉树为空,那么这个节点就当作跟节点

if bst.root == nil {

bst.root = newNode

} else {

insertNode(bst.root, newNode)

}

}

// 从根节点依次比较

func insertNode(root, newNode *Node) {

if newNode.value < root.value { // 应该放到根节点的左边

if root.left == nil {

root.left = newNode

} else {

insertNode(root.left, newNode)

}

} else if newNode.value > root.value { // 应该放到根节点的右边

if root.right == nil {

root.right = newNode

} else {

insertNode(root.right, newNode)

}

}

// 否则等于根节点

}

删除有些麻烦,如果是删除叶节点就比较容易,删除即可。但是如果不是删除叶节点,那么就需要将子节点提升。

// Remove 删除一个元素.

func (bst *BST) Remove(value int) bool {

_, existed := remove(bst.root, value)

return existed

}

// 用来递归移除节点的辅助方法.

// 返回替换root的新节点,以及元素是否存在

func remove(root *Node, value int) (*Node, bool) {

if root == nil {

return nil, false

}

var existed bool

// 从左边找

if value < root.value {

root.left, existed = remove(root.left, value)

return root, existed

}

// 从右边找

if value > root.value {

root.right, existed = remove(root.right, value)

return root, existed

}

// 如果此节点正是要移除的节点,那么返回此节点,同时返回之前可能需要调整.

existed = true

// 如果此节点没有孩子,直接返回即可

if root.left == nil && root.right == nil {

root = nil

return root, existed

}

// 如果左子节点为空, 提升右子节点

if root.left == nil {

root = root.right

return root, existed

}

// 如果右子节点为空, 提升左子节点

if root.right == nil {

root = root.left

return root, existed

}

// 如果左右节点都存在,那么从右边节点找到一个最小的节点提升,这个节点肯定比左子树所有节点都大.

// 也可以从左子树节点中找一个最大的提升,道理一样.

smallestInRight, _ := min(root.right)

// 提升

root.value = smallestInRight

// 从右边子树中移除此节点

root.right, _ = remove(root.right, smallestInRight)

return root, existed

}

搜索

检查一个节点是否存在比较简单,因为二叉搜索树是有序的。

// Search 搜索元素(检查元素是否存在)

func (bst *BST) Search(value int) bool {

return search(bst.root, value)

}

func search(n *Node, value int) bool {

if n == nil {

return false

}

if value < n.value {

return search(n.left, value)

}

if value > n.value {

return search(n.right, value)

}

return true

}

同时,我们还可以实现查找一个二叉搜索树的最大最小值。

func (bst *BST) Min() (int, bool) {

return min(bst.root)

}

func min(node *Node) (int, bool) {

if node == nil {

return 0, false

}

n := node

// 从左边找

for {

if n.left == nil {

return n.value, true

}

n = n.left

}

}

// Max 二叉搜索树中的最大值

func (bst *BST) Max() (int, bool) {

return max(bst.root)

}

func max(node *Node) (int, bool) {

if node == nil {

return 0, false

}

n := node

// 从右边找

for {

if n.right == nil {

return n.value, true

}

n = n.right

}

}

遍历

可以实现先序遍历、中序遍历和后序遍历,先中后指的是根节点相对子节点的处理顺序。

// PreOrderTraverse 前序遍历

func (bst *BST) PreOrderTraverse(f func(int)) {

preOrderTraverse(bst.root, f)

}

func preOrderTraverse(n *Node, f func(int)) {

if n != nil {

f(n.value) // 前

preOrderTraverse(n.left, f)

preOrderTraverse(n.right, f)

}

}

// PostOrderTraverse 后序遍历

func (bst *BST) PostOrderTraverse(f func(int)) {

postOrderTraverse(bst.root, f)

}

func postOrderTraverse(n *Node, f func(int)) {

if n != nil {

postOrderTraverse(n.left, f)

postOrderTraverse(n.right, f)

f(n.value) // 后

}

}

go 递归tree关系_Go实现一个二叉搜索树相关推荐

  1. 阿里开发者招聘节 | 面试题02-04:给定一个二叉搜索树(BST),找到树中第K小的节点

    为帮助开发者们提升面试技能.有机会入职阿里,云栖社区特别制作了这个专辑--阿里巴巴资深技术专家们结合多年的工作.面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总 ...

  2. 【Java 数据结构】实现一个二叉搜索树

    目录 1.认识二叉搜索树 2.实现一个二叉搜索树 2.1 成员变量 2.2 insert 方法 2.3 search 方法 2.4 remove 方法(重点) 3.二叉搜索树总结 1.认识二叉搜索树 ...

  3. 实现一个二叉搜索树(Binary Search Tree)

    文章目录 定义 代码实现 一.Github代码地址 二.节点 三.树实现接口 四.4种遍历方式 五.搜索 六.删除 七.插入 结尾 定义 二叉搜索树(Binary Search Tree),又名二叉排 ...

  4. PAT甲级1043 Is It a Binary Search Tree :[C++题解]判断二叉搜索树BST、给定前序序列和中序序列

    文章目录 题目分析 题目链接 题目分析 二叉搜索树(BST):左子树小于根结点,右子树大于等于根结点. 二叉搜索树的中序遍历一定是有序序列.所谓中序遍历:先访问左子树,再访问根结点,最后访问右子树. ...

  5. HDU3999 The order of a Tree【二叉搜索树 + 前序遍历】

    The order of a Tree 题意: 给定一个二叉搜索树的插入顺序,要求输出建树之后的前序遍历. 题解: 连续第二天做到二叉搜索树了,真的吹爆这个算法,从二叉树啥也不懂,到简单搜索树直接秒杀 ...

  6. The order of a Tree hdu3999 二叉搜索树

    题目链接: hdu3999 The order of a Tree 题意: 给一个二叉搜索树的序列,求输出可以构成这个二叉搜索树的且满足字典序最小的插入序列 找了一个比较具体描述怎么根据序列建立二叉搜 ...

  7. LeetCode 669. Trim a Binary Search Tree修剪二叉搜索树 (C++)

    题目: Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so th ...

  8. 高级数据结构与算法 | 二叉搜索树(Binary Search Tree)

    文章目录 二叉搜索树的概念 二叉搜索树的作用 排序 查找 实现思路 查找 插入 删除 删除.拷贝等 代码实现 K模型 KV模型 二叉搜索树的概念 二叉搜索树又叫做二叉排序树,他是一个具有以下特性的二叉 ...

  9. 题目一:给出一个n,代表有从1到n的数字[1,2,3,··· n],问可以构成多少种二叉搜索树?...

    题目一:给出一个n,代表有从1到n的数字[1,2,3,··· n],问可以构成多少种二叉搜索树? 一开始的想法是直接递归构造,时间复杂度是指数上升: 后来想法是找规律: 先看例子: n = 1, 有一 ...

最新文章

  1. 如何将h5网页改成微信网页
  2. Django中模型类 属性-学习笔记
  3. java 反射 ibm_Java编程语言构建IBM InfoSphere Streams程序(3)
  4. JVM内存划分、Linux用户态、内核态简介
  5. Oracle/MySQL/PostgreSQL考题等你挑战(附假期活动获奖名单)
  6. 二分查找算法(C#实现)
  7. Poi实现Excel的导入
  8. AndroidのTextView之CompoundDrawable那些坑
  9. Scrum项目6.0 和8910章读后感
  10. 自然语言交流系统 phxnet团队 创新实训 个人博客 (十一)
  11. 利用 openresty balancer_by_lua 实现一个简单的 ip_hash upstream 调度
  12. 个人对游戏加速器行业看法(一):概念介绍
  13. Python购物车系统模拟1
  14. 腾讯大厂2022校招来啦
  15. 六、Python文件操作
  16. vue中的prop验证
  17. C语言串口通信R8T8,K60-串口通信
  18. mac搭建win10虚拟机并对磁盘分区
  19. 程序员视角下对ChatGPT热潮的思考
  20. Compute Shader次世代优化方案

热门文章

  1. 将View兑换Bitmap
  2. 【原创】轻量级移动端即时通讯技术 MobileIMSDK 发布了
  3. 手把手教你调试Linux C++ 代码(一步到位包含静态库和动态库调试)
  4. 开源 Asp.net mvc 用户中心(nUserCenter) 产品机会评估
  5. java写算法之二叉搜索树查找
  6. c语言结构体语法分析,C语言结构体struct的语法解析
  7. net.conn read 判断数据读取完毕_单方验方|如何应对千万级工商数据抓取(一)
  8. Python使用多线程搜索指定范围内的所有素数
  9. pythonlambda回调函数_Python中如何借助lambda来给回调函数传参
  10. IP地这和子网的划分