首页 > 其他分享 >Go平衡二叉树

Go平衡二叉树

时间:2024-09-02 10:14:11浏览次数:2  
标签:right nil AVLNode height 二叉树 Go 平衡 data left

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")
}

标签:right,nil,AVLNode,height,二叉树,Go,平衡,data,left
From: https://www.cnblogs.com/qcy-blog/p/18392249

相关文章

  • 排序算法之二叉树排序详细解读(附带Java代码解读)
    二叉树排序(BinaryTreeSort)是一种基于二叉搜索树(BinarySearchTree,BST)实现的排序算法。它的基本思想是利用二叉搜索树的性质来实现排序,通过将元素插入到二叉搜索树中,然后对树进行中序遍历来获取排序后的元素。基本概念二叉搜索树(BST):对于二叉搜索树中的每一个节点,其左......
  • python django 使用教程
    前言pythondjango使用起来简单方便,大大节省开发时间,提高开发效率,现在介绍下如何使用一、创建Django项目首先,建立虚拟环境,(最好养成一个项目一个环境的习惯,防止多个项目pip包混乱问题),打开pycharm新建Django项目(专业版才可以有这个功能,网上搜一下,一大堆方法,懂得都懂......
  • PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
    大家好,我是码农先森。我们在某宝或某多多上抢购商品时,如果只是下了订单但没有进行实际的支付,那在订单页面会有一个支付倒计时,要是过了这个时间点那么订单便会自动取消。在这样的业务场景中,一般情况下就会使用到延时队列。通常在客户下单之后,就会将订单数据推送到延时队列中并且......
  • GOBY联合AWVS
    一:打开goby,点击拓展程序二:搜索wavs,点击下载三:点击设置,拓展设置四:输入awvs的APIKey以及awvs地址(确保地址能访问)五:设置成功后再goby里面新建扫描(我这里扫描的自己搭建的网站)。六:扫描完成以后点击资产,点ip详情七:点击详情后如下八:点击wavs后,点击拓展程序,会弹出一个页......
  • GOBY联合XRAY
    一:下载xray和rad(结尾附链接)二:添加xray和rad路径三:需要使用xray与rad的先用goby扫描完目标如图四:点击资产,点击xray-crawler会出现弹窗五:开启被动扫描监听六:扫描完成后可查看报告七:Xray-GUI模式八:也可以查看报告注:每次网络环境变化都需要去xray和rad目录下新运行......
  • 二叉树的直径(LeetCode)
    题目给你一棵二叉树的根节点,返回该树的 直径 。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之间边数表示。解题classTreeNode:def__init__(self,val=0,left=......
  • Go入门:gin框架极速搭建图书管理系统
    Go入门:gin框架极速搭建图书管理系统前言本项目适合Golang初学者,通过简单的项目实践来加深对Golang的基本语法和Web开发的理解。项目源码请私信,欢迎前往博主博客torna.top免费查看。项目结构D:.├─go.mod├─go.sum│├─cmd│└─main│......
  • Study Plan For Algorithms - Part18
    1.搜索插入位置题目链接:https://leetcode.cn/problems/search-insert-position/给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。classSolution:defsearchInsert(self,nums:List[int],target:......
  • 花店鲜花管理与推荐系统+Python+Django网页界面+管理系统+计算机课设
    一、介绍花店鲜花管理与推荐系统。本系统使用Python作为主要开发语言开发的一个花店鲜花管理与推荐的网站平台。网站前端界面采用HTML、CSS、BootStrap等技术搭建界面。后端采用Django框架处理用户的逻辑请求,并将用户的相关行为数据保存在数据库中。通过Ajax技术实现前后端的数......
  • 代码随想录刷题day13丨二叉树理论基础,递归遍历,迭代遍历,统一迭代,层序遍历
    代码随想录刷题day13丨二叉树理论基础,递归遍历,迭代遍历,统一迭代,层序遍历1.二叉树理论基础1.1二叉树种类满二叉树概述:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节......