go 递归tree关系_Go实现一个二叉搜索树
什么是二叉搜索树
二叉搜索树(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实现一个二叉搜索树相关推荐
- 阿里开发者招聘节 | 面试题02-04:给定一个二叉搜索树(BST),找到树中第K小的节点
为帮助开发者们提升面试技能.有机会入职阿里,云栖社区特别制作了这个专辑--阿里巴巴资深技术专家们结合多年的工作.面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总 ...
- 【Java 数据结构】实现一个二叉搜索树
目录 1.认识二叉搜索树 2.实现一个二叉搜索树 2.1 成员变量 2.2 insert 方法 2.3 search 方法 2.4 remove 方法(重点) 3.二叉搜索树总结 1.认识二叉搜索树 ...
- 实现一个二叉搜索树(Binary Search Tree)
文章目录 定义 代码实现 一.Github代码地址 二.节点 三.树实现接口 四.4种遍历方式 五.搜索 六.删除 七.插入 结尾 定义 二叉搜索树(Binary Search Tree),又名二叉排 ...
- PAT甲级1043 Is It a Binary Search Tree :[C++题解]判断二叉搜索树BST、给定前序序列和中序序列
文章目录 题目分析 题目链接 题目分析 二叉搜索树(BST):左子树小于根结点,右子树大于等于根结点. 二叉搜索树的中序遍历一定是有序序列.所谓中序遍历:先访问左子树,再访问根结点,最后访问右子树. ...
- HDU3999 The order of a Tree【二叉搜索树 + 前序遍历】
The order of a Tree 题意: 给定一个二叉搜索树的插入顺序,要求输出建树之后的前序遍历. 题解: 连续第二天做到二叉搜索树了,真的吹爆这个算法,从二叉树啥也不懂,到简单搜索树直接秒杀 ...
- The order of a Tree hdu3999 二叉搜索树
题目链接: hdu3999 The order of a Tree 题意: 给一个二叉搜索树的序列,求输出可以构成这个二叉搜索树的且满足字典序最小的插入序列 找了一个比较具体描述怎么根据序列建立二叉搜 ...
- 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 ...
- 高级数据结构与算法 | 二叉搜索树(Binary Search Tree)
文章目录 二叉搜索树的概念 二叉搜索树的作用 排序 查找 实现思路 查找 插入 删除 删除.拷贝等 代码实现 K模型 KV模型 二叉搜索树的概念 二叉搜索树又叫做二叉排序树,他是一个具有以下特性的二叉 ...
- 题目一:给出一个n,代表有从1到n的数字[1,2,3,··· n],问可以构成多少种二叉搜索树?...
题目一:给出一个n,代表有从1到n的数字[1,2,3,··· n],问可以构成多少种二叉搜索树? 一开始的想法是直接递归构造,时间复杂度是指数上升: 后来想法是找规律: 先看例子: n = 1, 有一 ...
最新文章
- 如何将h5网页改成微信网页
- Django中模型类 属性-学习笔记
- java 反射 ibm_Java编程语言构建IBM InfoSphere Streams程序(3)
- JVM内存划分、Linux用户态、内核态简介
- Oracle/MySQL/PostgreSQL考题等你挑战(附假期活动获奖名单)
- 二分查找算法(C#实现)
- Poi实现Excel的导入
- AndroidのTextView之CompoundDrawable那些坑
- Scrum项目6.0 和8910章读后感
- 自然语言交流系统 phxnet团队 创新实训 个人博客 (十一)
- 利用 openresty balancer_by_lua 实现一个简单的 ip_hash upstream 调度
- 个人对游戏加速器行业看法(一):概念介绍
- Python购物车系统模拟1
- 腾讯大厂2022校招来啦
- 六、Python文件操作
- vue中的prop验证
- C语言串口通信R8T8,K60-串口通信
- mac搭建win10虚拟机并对磁盘分区
- 程序员视角下对ChatGPT热潮的思考
- Compute Shader次世代优化方案
热门文章
- 将View兑换Bitmap
- 【原创】轻量级移动端即时通讯技术 MobileIMSDK 发布了
- 手把手教你调试Linux C++ 代码(一步到位包含静态库和动态库调试)
- 开源 Asp.net mvc 用户中心(nUserCenter) 产品机会评估
- java写算法之二叉搜索树查找
- c语言结构体语法分析,C语言结构体struct的语法解析
- net.conn read 判断数据读取完毕_单方验方|如何应对千万级工商数据抓取(一)
- Python使用多线程搜索指定范围内的所有素数
- pythonlambda回调函数_Python中如何借助lambda来给回调函数传参
- IP地这和子网的划分