(三)用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的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
随机推荐
- Ribbon负载均衡 (源码分析)
Ribbon负载均衡 SpringCloud已经删除了ribbon组件,所以需要手动导入依赖.(要学是因为很多项目业务已经使用了ribbon) 服务拉取的时候添加了@LoadBalanced注解,实现 ...
- .NET 中的并发编程
今天我们购买的每台电脑都有一个多核心的 CPU,允许它并行执行多个指令.操作系统通过将进程调度到不同的内核来发挥这个结构的优点.然而,还可以通过异步 I/O 操作和并行处理来帮助我们提高单个应用程序的 ...
- 2.17 win32 按钮事件的处理
按钮的本质就是窗口 点击查看代码 void CreateButton(HWND hwnd) { HWND hwndPushButton; HWND hwndCheckBox; HWND hwndRad ...
- 高仿微信|基于Windows微信实现一个IM即时通讯App
本文干货充足篇幅较长,建议收藏后阅读避免迷路.文末可获取[自动聊天机器人源码和Demo]. 即时通讯IM概述 如果能开发一款即时聊天App,能和微信消息互通,并且只需少许代码量,应该是件非常兴奋的事情 ...
- wpf 样式style封装以及点击按钮打开新窗口
在页面引用: ok~ 点击按钮打开新窗口: 1.点击按钮 点击工具栏的这个小闪电 2.双击click后的灰框或者输入点击事件名称 3.这里是打开window1窗口 ok~
- ERROR: Functions in index expression must be marked IMMUTABLE
在创建函数索引时遇到报错,报错信息即为标题,下面是详细信息. 1 表定义 1234567 skytf=> \d test_39; Table "skytf.test_39" ...
- ChatGPT强势爆红,背后的技术原理是?一文轻松搞懂!
目录 什么是ChatGPT? OpenAI 背后的原理和发展历程 带来的争议和挑战 尾语 作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.源码解析.科技故事.项目 ...
- 看完这一篇,ShardingSphere-jdbc 实战再也不怕了
谈到分库分表中间件时,我们自然而然的会想到 ShardingSphere-JDBC . 这篇文章,我们聊聊 ShardingSphere-JDBC 相关知识点,并实战演示一番. 1 ShardingS ...
- LeetCode-380 O(1)时间插入、删除和获取随机元素
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/insert-delete-getrandom-o1 题目描述 实现RandomizedSet 类 ...
- CRM管理系统界面