(三)用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的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
随机推荐
- .Net Framework创建grpc
1.环境要求 .Net Framework 4.8 .Net Core 版本: https://www.cnblogs.com/dennisdong/p/17120990.html 2.Stub和Pr ...
- TCP/IP协议(1): IP 地址和寻址方式 —— IP 协议的基础
TCP/IP协议(1): IP 地址和寻址方式 -- IP 协议的基础 最近在重学计算机网络,给自己立一个 flag,有感而发的时候写关于 TCP/IP 协议栈的系列博客. IP 地址 IP 地址(I ...
- K8S发布应用步骤详解
前言 首先以SpringBoot应用为例介绍一下k8s的发布步骤. 1.从代码仓库下载代码,比如GitLab: 2.接着是进行打包,比如使用Maven: 3.编写Dockerfile文件,把步骤2产生 ...
- 使用NAT网络模式搭建内网,修改IP地址
使用NAT网络模式搭建内网,修改IP地址 首先说明一下虚拟机的三种联网方式: 桥接模式: 简单来说就是使这台虚拟机成为一台在互联网中的有独立IP的一台新设备和Mac地址(不够都是虚拟的) NAT模式: ...
- LeetCode 周赛 334,在算法的世界里反复横跳
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 今天是 LeetCode 第 334 场周赛,你参加了吗?这场周赛考察范围比较基础,整体 ...
- 使用vscode编辑markdown
目录 markdown在vscode中的使用 标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 列表 图片 表格 网址 代码 文本样式 引用 目录 vscode中使用的插件推荐 截图工 ...
- AOP 编程
1.静态代理 定义一个接口,用以规定执行方法 public interface IOrderProcessor { void Submit(); } 实现执行方法 public class Order ...
- linux 进程组和会话 守护进程
这两个概念的产生,是为了shell更好的管理作业,管理其创建的子进程 对其进行暂停,终止 执行命令,命令之间有时还需要管道进行通信 进程组是进程的合集 会话是进程组的合集 一个会话共用一个控制终端,也 ...
- word2021自带viso屏幕闪烁、抖动问题解决
文件--选项-->高级-->显示-->勾选禁用硬件图像加速
- Vicinity Vision Transformer概述
0.前言 相关资料: arxiv github 论文解读 论文基本信息: 发表时间:arxiv2022(2022.6.21) 1.针对的问题 视觉transformer计算复杂度和内存占用都是二次的, ...