(三)用go实现平衡二叉树
本篇,我们用go简单的实现平衡二叉查找树。具体原理参考大佬博客即可:AVL树(一)之 图文解析 和 C语言的实现
1.节点定义
type AVLNode struct{
data int
height int
left, right *AVLNode
}
2.树的遍历
// 前序遍历
func PreTraverse(p *AVLNode) {
if p == nil {
return
}
fmt.Printf("%d:%d ", p.data, p.height)
if p.left != nil {
PreTraverse(p.left)
}
if p.right != nil {
PreTraverse(p.right)
}
}
// 中序遍历
func InTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
InTraverse(p.left)
}
fmt.Printf("%d ", p.data)
if p.right != nil {
InTraverse(p.right)
}
}
// 后序遍历
func PostTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
PostTraverse(p.left)
}
if p.right != nil {
PostTraverse(p.right)
}
fmt.Printf("%d ", p.data)
}
3.树的旋转
// LL的旋转
func ll_rotate(k2 *AVLNode) *AVLNode {
var k1 *AVLNode = k2.left
k2.left = k1.right
k1.right = k2
k2.height = max(height(k2.left), height(k2.right)) + 1
k1.height = max(height(k1.left), k2.height) + 1
return k1
}
// RR的旋转
func rr_rotate(k1 *AVLNode) *AVLNode {
var k2 *AVLNode = k1.right
k1.right = k2.left
k2.left = k1
k1.height = max(height(k1.left), height(k1.right)) + 1
k2.height = max(height(k2.right), k1.height) + 1
return k2
}
// LR的旋转
func lr_rotate(k3 *AVLNode) *AVLNode {
k3.left = rr_rotate(k3.left)
return ll_rotate(k3)
}
// RL的旋转
func rl_rotate(k1 *AVLNode) *AVLNode {
k1.right = ll_rotate(k1.right)
return rr_rotate(k1)
}
4.插入节点
// 插入节点
func Add(p *AVLNode, data int) *AVLNode {
if p == nil {
p = new(AVLNode)
p.data = data
p.height = 1
return p
}
if data < p.data {
p.left = Add(p.left, data)
if height(p.left) - height(p.right) == 2 {
if data > p.left.data {
fmt.Println("lr")
p = lr_rotate(p)
} else {
fmt.Println("ll")
p = ll_rotate(p)
}
}
} else if data > p.data {
p.right = Add(p.right, data)
if height(p.right) - height(p.left) == 2{
if data > p.right.data {
fmt.Println("rr")
p = rr_rotate(p)
} else {
fmt.Println("rl")
p = rl_rotate(p)
}
}
} else {
fmt.Println("Add fail: not allowed same data!")
}
p.height = max(height(p.left), height(p.right)) + 1
fmt.Printf("节点:%d, 高度:%d\n", p.data, p.height)
return p
}
5.查询节点
// 查询节点
func Find(p *AVLNode, data int) *AVLNode {
if p.data == data {
return p
} else if data < p.data {
if p.left != nil {
return Find(p.left, data)
}
return nil
} else {
if p.right != nil {
return Find(p.right, data)
}
return nil
}
}
// 最大节点
func maxNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.right != nil {
p = p.right
}
return p
}
// 最小节点
func minNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.left != nil {
p = p.left
}
return p
}
6.删除节点
// 删除节点
func Delete(p *AVLNode, data int) *AVLNode {
node := Find(p, data)
if node != nil {
return delete(p, node)
}
return nil
}
func delete(p, node *AVLNode) *AVLNode {
if node.data < p.data {
p.left = delete(p.left, node)
if height(p.right) - height(p.left) == 2 {
if height(p.right.right) > height(p.right.left) {
p = rr_rotate(p)
} else {
p = rl_rotate(p)
}
}
} else if node.data > p.data {
p.right = delete(p.right, node)
if height(p.left) - height(p.right) == 2 {
if height(p.left.right) > height(p.left.left) {
p = lr_rotate(p)
} else {
p = ll_rotate(p)
}
}
} else {
// 左右孩子都非空
if (p.left != nil) && (p.right != nil) {
if height(p.left) > height(p.right) {
var max *AVLNode = maxNode(p.left)
p.data = max.data
p.left = delete(p.left, max)
} else {
var min *AVLNode = minNode(p.right)
p.data = min.data
p.right = delete(p.right, min)
}
} else {
if p.left != nil {
p = p.left
} else {
p = p.right
}
}
}
if p != nil {
p.height = max(height(p.left), height(p.right)) + 1
}
return p
}
7.完整代码
package main
import (
"fmt"
)
type AVLNode struct{
data int
height int
left, right *AVLNode
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func height(p *AVLNode) int {
if p != nil {
return p.height
}
return 0
}
// 前序遍历
func PreTraverse(p *AVLNode) {
if p == nil {
return
}
fmt.Printf("%d:%d ", p.data, p.height)
if p.left != nil {
PreTraverse(p.left)
}
if p.right != nil {
PreTraverse(p.right)
}
}
// 中序遍历
func InTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
InTraverse(p.left)
}
fmt.Printf("%d ", p.data)
if p.right != nil {
InTraverse(p.right)
}
}
// 后序遍历
func PostTraverse(p *AVLNode) {
if p == nil {
return
}
if p.left != nil {
PostTraverse(p.left)
}
if p.right != nil {
PostTraverse(p.right)
}
fmt.Printf("%d ", p.data)
}
// LL的旋转
func ll_rotate(k2 *AVLNode) *AVLNode {
var k1 *AVLNode = k2.left
k2.left = k1.right
k1.right = k2
k2.height = max(height(k2.left), height(k2.right)) + 1
k1.height = max(height(k1.left), k2.height) + 1
return k1
}
// RR的旋转
func rr_rotate(k1 *AVLNode) *AVLNode {
var k2 *AVLNode = k1.right
k1.right = k2.left
k2.left = k1
k1.height = max(height(k1.left), height(k1.right)) + 1
k2.height = max(height(k2.right), k1.height) + 1
return k2
}
// LR的旋转
func lr_rotate(k3 *AVLNode) *AVLNode {
k3.left = rr_rotate(k3.left)
return ll_rotate(k3)
}
// RL的旋转
func rl_rotate(k1 *AVLNode) *AVLNode {
k1.right = ll_rotate(k1.right)
return rr_rotate(k1)
}
// 插入节点
func Add(p *AVLNode, data int) *AVLNode {
if p == nil {
p = new(AVLNode)
p.data = data
p.height = 1
return p
}
if data < p.data {
p.left = Add(p.left, data)
if height(p.left) - height(p.right) == 2 {
if data > p.left.data {
fmt.Println("lr")
p = lr_rotate(p)
} else {
fmt.Println("ll")
p = ll_rotate(p)
}
}
} else if data > p.data {
p.right = Add(p.right, data)
if height(p.right) - height(p.left) == 2{
if data > p.right.data {
fmt.Println("rr")
p = rr_rotate(p)
} else {
fmt.Println("rl")
p = rl_rotate(p)
}
}
} else {
fmt.Println("Add fail: not allowed same data!")
}
p.height = max(height(p.left), height(p.right)) + 1
fmt.Printf("节点:%d, 高度:%d\n", p.data, p.height)
return p
}
// 查询节点
func Find(p *AVLNode, data int) *AVLNode {
if p.data == data {
return p
} else if data < p.data {
if p.left != nil {
return Find(p.left, data)
}
return nil
} else {
if p.right != nil {
return Find(p.right, data)
}
return nil
}
}
// 最大节点
func maxNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.right != nil {
p = p.right
}
return p
}
// 最小节点
func minNode(p *AVLNode) *AVLNode {
if p == nil {
return nil
}
for p.left != nil {
p = p.left
}
return p
}
// 删除节点
func Delete(p *AVLNode, data int) *AVLNode {
node := Find(p, data)
if node != nil {
return delete(p, node)
}
return nil
}
func delete(p, node *AVLNode) *AVLNode {
if node.data < p.data {
p.left = delete(p.left, node)
if height(p.right) - height(p.left) == 2 {
if height(p.right.right) > height(p.right.left) {
p = rr_rotate(p)
} else {
p = rl_rotate(p)
}
}
} else if node.data > p.data {
p.right = delete(p.right, node)
if height(p.left) - height(p.right) == 2 {
if height(p.left.right) > height(p.left.left) {
p = lr_rotate(p)
} else {
p = ll_rotate(p)
}
}
} else {
// 左右孩子都非空
if (p.left != nil) && (p.right != nil) {
if height(p.left) > height(p.right) {
var max *AVLNode = maxNode(p.left)
p.data = max.data
p.left = delete(p.left, max)
} else {
var min *AVLNode = minNode(p.right)
p.data = min.data
p.right = delete(p.right, min)
}
} else {
if p.left != nil {
p = p.left
} else {
p = p.right
}
}
}
if p != nil {
p.height = max(height(p.left), height(p.right)) + 1
}
return p
}
func main() {
//num := []int{50, 30, 20, 25, 70, 90, 100}
num := []int{3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9}
var root *AVLNode
for _, v := range num {
fmt.Printf("插入节点:%d\n", v)
root = Add(root, v)
}
fmt.Println("前序遍历:")
PreTraverse(root)
fmt.Printf("\n")
fmt.Println("中序遍历:")
InTraverse(root)
fmt.Printf("\n")
fmt.Println("后序遍历:")
PostTraverse(root)
fmt.Printf("\n")
avlnode := Find(root, 60)
if avlnode != nil {
fmt.Println("查询结果:")
fmt.Printf("节点:%d 左子节点:%d 右子节点:%d\n", avlnode.data, avlnode.left.data, avlnode.right.data)
}
root = Delete(root, 8)
fmt.Println("删除后前序遍历:")
PreTraverse(root)
fmt.Printf("\n")
fmt.Println("删除后中序遍历:")
InTraverse(root)
fmt.Printf("\n")
}
(三)用go实现平衡二叉树的更多相关文章
- 剑指offer三十九之平衡二叉树
一.题目 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 二.思路 详解代码. 三.代码 public class Solution { //判断根节点左右子树的深度,高度差超过1,则不平衡 ...
- Java开发笔记(六十六)映射:HashMap和TreeMap
前面介绍了两种集合的用法,它们的共性为每个元素都是唯一的,区别在于一个无序一个有序.虽说往集合里面保存数据还算容易,但要从集合中取出数据就没那么方便了,因为集合居然不提供get方法,没有get方法怎么 ...
- 树(三)——自平衡二叉树(AVL)
简介 自平衡二叉树(AVL)属于二叉平衡树的一类,此类树主要完成一个从键到值的查找过程,即字典(或映射),它维护树高度的方式与其他数据结构不同. 自平衡规则: AVL树的左.右子树都是AVL树 左.右 ...
- 树结构(三)----平衡二叉树(AVL树)
将二叉排序树的的缺点优化,继承二叉排序的树的优化 左子树和右子树的高度差的绝对值不超过1
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
- 平衡二叉树AVL删除
平衡二叉树的插入过程:http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p,其双亲是 ...
- 数据结构快速回顾——平衡二叉树 AVL (转)
平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...
- 数据结构之平衡二叉树(AVL树)
平衡二叉树(AVL树)定义如下:平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树: (1)它的左子树和右子树的高度之差绝对值不超过1: (2)它的左子树和右子树都是平衡二叉树. AVL树避免了 ...
- 一步一步写平衡二叉树(AVL树)
平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...
- 平衡二叉树,AVL树之图解篇
学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
随机推荐
- Ceph RGW误删index对象恢复
版本 [root@control1 ~]# ceph -v ceph version 14.2.22 (ca74598065096e6fcbd8433c8779a2be0c889351) nautil ...
- JDBC工具类,减少代码冗余好帮手
首先要在scr下创建一个file文件 当然 需要初始的注册驱动和数据库操作都可以实现,才可以用jdbc工具类进行减多少代码冗余~可以看前面一篇的博客,就是写如何连接jdbc哈~代码运行成功的快乐真的好 ...
- P14_协同工作-开发者的权限说明以及如何维护项目成员
不同项目成员对应的权限 开发者的权限说明 开发者权限:可使用小程序开发者工具及对小程序的功能进行代码开发 体验者权限:可使用体验版小程序 登录权限:可登录小程序管理后台,无需管理员确认 开发设置:设置 ...
- 学习Java Day26
今天看书学习JAR文件,但是看了半天并没有看懂,于是借助了B站学习了JAR文件的创建及其中的一些jar程序选项该怎么使用
- odoo 为可编辑列表视图字段搜索添加查询过滤条件
实践环境 Odoo 14.0-20221212 (Community Edition) 需求描述 如下图,列表网仓记录详情页面(form视图),编辑内联视图中的货主记录,为货主和仓库字段搜索,添加过滤 ...
- playwright 实现高亮、is_visible 等源码修改
一. 前言 高亮是什么? 在ui自动化中可以执行js来让某个页面元素高亮,比如背景颜色.字体颜色.边框颜色等发生改变,以此更加方便执行的时候点了哪一步操作.(如果有不清楚怎么实现的可以转到我的介绍se ...
- JZOJ 6800.NOIP2020.9.19模拟spongebob
题目大意 求形如 \[\sum_{i=1}^n |a_ix + b_i| \] 的最小值 思路 我们显然可以先把系数 \(a\) 提出来 于是就成了 \(\sum_{i=1}^n |a_i|·|x + ...
- Jquery 点击弹窗,将弹窗内容赋值到各个项demo
<div class="qb"> <div class="box"> <div class="qtt f_16 fbd& ...
- K8S 1.20 弃用 Docker 评估之 Docker CLI 的替代产品
title: K8S 1.20 弃用 Docker 评估之 Docker CLI 的替代产品 tags: - Docker - K8S - OCI - 容器 - 最佳实践 - RedHat - Sko ...
- 基于GLUT的PyOpenGL的使用
1. GLUT概述 OpenGL只是一种规范,不仅语言无关,而且平台无关.规范只字未提获得和管理OpenGL上下文相关的内容,而是将这些作为细节交给底层的窗口系统.出于同样的原因,OpenGL纯粹专注 ...