Go语言教程之边写边学:数据结构与算法:生成自平衡二叉查找树 AVL tree

2024-01-10 10:30 1040 阅读 Go语言教程之边写边学 #163

标签

AVL树是高度平衡的二叉搜索树。AVL树检查左侧和右侧子树的高度,并确保差异不超过1,这种差异称为平衡因子。

实现代码:

package main
 
import (
    "encoding/json"
    "fmt"
)

type Key interface {
    Less(Key) bool
    Eq(Key) bool
}
 

type Node struct {
    Data    Key
    Balance int
    Link    [2]*Node
}
 

func opp(dir int) int {
    return 1 - dir
}
 
// single rotation
func single(root *Node, dir int) *Node {
    save := root.Link[opp(dir)]
    root.Link[opp(dir)] = save.Link[dir]
    save.Link[dir] = root
    return save
}
 
// double rotation
func double(root *Node, dir int) *Node {
    save := root.Link[opp(dir)].Link[dir]
 
    root.Link[opp(dir)].Link[dir] = save.Link[opp(dir)]
    save.Link[opp(dir)] = root.Link[opp(dir)]
    root.Link[opp(dir)] = save
 
    save = root.Link[opp(dir)]
    root.Link[opp(dir)] = save.Link[dir]
    save.Link[dir] = root
    return save
}
 
// adjust valance factors after double rotation
func adjustBalance(root *Node, dir, bal int) {
    n := root.Link[dir]
    nn := n.Link[opp(dir)]
    switch nn.Balance {
    case 0:
        root.Balance = 0
        n.Balance = 0
    case bal:
        root.Balance = -bal
        n.Balance = 0
    default:
        root.Balance = 0
        n.Balance = bal
    }
    nn.Balance = 0
}
 
func insertBalance(root *Node, dir int) *Node {
    n := root.Link[dir]
    bal := 2*dir - 1
    if n.Balance == bal {
        root.Balance = 0
        n.Balance = 0
        return single(root, opp(dir))
    }
    adjustBalance(root, dir, bal)
    return double(root, opp(dir))
}
 
func insertR(root *Node, data Key) (*Node, bool) {
    if root == nil {
        return &Node{Data: data}, false
    }
    dir := 0
    if root.Data.Less(data) {
        dir = 1
    }
    var done bool
    root.Link[dir], done = insertR(root.Link[dir], data)
    if done {
        return root, true
    }
    root.Balance += 2*dir - 1
    switch root.Balance {
    case 0:
        return root, true
    case 1, -1:
        return root, false
    }
    return insertBalance(root, dir), true
}
 
// Insert a node into the AVL tree.
func Insert(tree **Node, data Key) {
    *tree, _ = insertR(*tree, data)
}

// Remove a single item from an AVL tree.
func Remove(tree **Node, data Key) {
    *tree, _ = removeR(*tree, data)
}

func removeBalance(root *Node, dir int) (*Node, bool) {
    n := root.Link[opp(dir)]
    bal := 2*dir - 1
    switch n.Balance {
    case -bal:
        root.Balance = 0
        n.Balance = 0
        return single(root, dir), false
    case bal:
        adjustBalance(root, opp(dir), -bal)
        return double(root, dir), false
    }
    root.Balance = -bal
    n.Balance = bal
    return single(root, dir), true
}
 
func removeR(root *Node, data Key) (*Node, bool) {
    if root == nil {
        return nil, false
    }
    if root.Data.Eq(data) {
        switch {
        case root.Link[0] == nil:
            return root.Link[1], false
        case root.Link[1] == nil:
            return root.Link[0], false
        }
        heir := root.Link[0]
        for heir.Link[1] != nil {
            heir = heir.Link[1]
        }
        root.Data = heir.Data
        data = heir.Data
    }
    dir := 0
    if root.Data.Less(data) {
        dir = 1
    }
    var done bool
    root.Link[dir], done = removeR(root.Link[dir], data)
    if done {
        return root, true
    }
    root.Balance += 1 - 2*dir
    switch root.Balance {
    case 1, -1:
        return root, true
    case 0:
        return root, false
    }
    return removeBalance(root, dir)
}
 

type intKey int 
func (k intKey) Less(k2 Key) bool { return k < k2.(intKey) }
func (k intKey) Eq(k2 Key) bool   { return k == k2.(intKey) }
 
func main() {
    var tree *Node
    fmt.Println("Empty Tree:")    
	avl,_ := json.MarshalIndent(tree, "", "   ")
	fmt.Println(string(avl))

    fmt.Println("\nInsert Tree:")
    Insert(&tree, intKey(4))
    Insert(&tree, intKey(2))
    Insert(&tree, intKey(7))
    Insert(&tree, intKey(6))
	Insert(&tree, intKey(6))
    Insert(&tree, intKey(9))
    avl,_ = json.MarshalIndent(tree, "", "   ")
	fmt.Println(string(avl))
 
    fmt.Println("\nRemove Tree:")
    Remove(&tree, intKey(4))
    Remove(&tree, intKey(6))
    avl,_ = json.MarshalIndent(tree, "", "   ")
	fmt.Println(string(avl))
}

输出:

Empty Tree:
null
Insert Tree:
{
   "Data": 6,
   "Balance": 0,
   "Link": [
      {
         "Data": 4,
         "Balance": 0,
         "Link": [
            {
               "Data": 2,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            },
            {
               "Data": 6,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            }
         ]
      },
      {
         "Data": 7,
         "Balance": 1,
         "Link": [
            null,
            {
               "Data": 9,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            }
         ]
      }
   ]
}
Remove Tree:
{
   "Data": 6,
   "Balance": 1,
   "Link": [
      {
         "Data": 2,
         "Balance": 0,
         "Link": [
            null,
            null
         ]
      },
      {
         "Data": 7,
         "Balance": 1,
         "Link": [
            null,
            {
               "Data": 9,
               "Balance": 0,
               "Link": [
                  null,
                  null
               ]
            }
         ]
      }
   ]
}

相关 AI 工具

Kilo Code Kilo Code Kilo Code 是完全开源(MIT)的 AI 编程代理,可在 IDE、CLI 与云端运行:统一代理门户管理本地/云代理、并行隔离 worktrees 与 IDE/CLI 会话;支持 500+ 模型零加价、自带 API Key(BYOK)、本地模型与 Auto Model 智能路由(Efficient/Frontier/Free);含 Code/Architect/Debug/Ask/Custom 多种模式,覆盖 VS Code、JetBrains、CLI、Cloud Agents、Slack、Code Reviewer、Gateway 等。免费层可用,已被 Anaconda 收购。 逗逗游戏伙伴 逗逗游戏伙伴 心影随形(LynkSoul)推出的 AI 游戏陪伴伙伴:VLM 实时看懂游戏画面,提供攻略、语音连麦与跨游戏记忆,AI 角色陪你玩游戏 书生 InternAI 书生 InternAI 书生·InternAI(上海人工智能实验室「书生」通用大模型体系官方门户)是开源、开放的大模型体系,涵盖书生·浦语(InternLM)大语言模型、书生·万象(InternVL)多模态模型,以及风乌气象、翼飞航空、天际三维、济世金融、言普谱学等垂直领域 AI 系统,提供全链条工具链与开源赋能。 INCLUSION AI INCLUSION AI 由蚂蚁集团支持、面向全球的开放 AGI 研究与协作平台(Open by Default):发布并开源多模态生成模型(如 Ming-Omni-TTS 精准控制的语音/音乐/声音统一生成、Ming-flash-omni 稀疏统一多模态架构),参与 vLLM/SGLang 等推理框架生态,聚焦 Agentic AI 趋势,为学习者与构建者提供可持续、负责任的智能选项。 Emdash Emdash 开源代理式开发环境(Agentic IDE):在隔离 Git worktree 中并行调度 25+ 编码代理,打通 Linear/Jira/GitHub 上下文,支持浏览器预览、SSH 远程与定时任务,一处完成开发、审查与交付。 Codewhale Codewhale Codewhale 是运行在终端里的开源编程智能体(MIT 许可):给它一个模型和一个任务,它会读取代码库、修改文件并运行检查,活干完或需要你拿主意时停下;支持 45 个模型提供商(托管 API、网关或 Ollama/vLLM/SGLang 本地运行时),Fleet 可为每个角色单独配模型;提供 Plan/Work/Operate 三种模式与 Ask/Auto-Review/Full Access 三档权限,界面覆盖交互式 TUI、exec(脚本与 CI)、本机 Web 客户端以及 Runtime API + MCP。
查看全部 AI 工具 →

相关提示词