mysql 遍历二叉树_数据结构与算法 - 各类二叉树的概述以及二叉树遍历的三种方式...

本文介绍了二叉树的种类,包括满二叉树、完全二叉树、平衡二叉树和二叉搜索树的概念与特性。详细解释了二叉搜索树与B树、B+树的区别,并探讨了为何MySQL会选择使用B+树作为索引结构。同时,文章还提供了二叉树前序、中序和后序遍历的代码实现。
摘要由CSDN通过智能技术生成

二叉树的种类

满二叉树

54562eaa968f009c0009c75fc63ef429.png

如上图所示,满二叉树的性质如下:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。

第k层上的节点数为: 2^(k-1)

一个层数为k的满二叉树的总结点数为: (2^k) - 1

完全二叉树

94bbee90659bcfa62d8be631b341c1a2.png

如上图所示,满二叉树的性质如下:在满二叉树的基础上,最底层从右往左删去若干节点,得到的都是完全二叉树

最低层可以不满,但最底层的节点都必须集中在最左边,也就是说次底层的节点一定会有左子节点,但可能没有右子节点

如果对一棵有n个结点的完全二叉树的结点按层序编号, 则对任一结点i (1≤i≤n):如果i=1, 则结点i是二叉树的根, 无双亲;如果i>1, 则i节点的父节点是i/2(取整,不四舍五入)

如果2i>n, 则结点i无左孩子, 否则其左孩子是结点2i;

如果2i+1>n, 则结点i无右孩子, 否则其右孩子是结点2i+1

平衡二叉树

08eacdd46d5290d56b0ebdaa51be7786.png树的左右子树的高度差不超过1的数

空树也是平衡二叉树的一种

二叉搜索树

d1118f240b986897b5cb76eb4e5b854d.png二叉搜索树的特点:对于树中的每个节点,它的左子树中所有关键字值小于父节点关键字值,而它的右子树中所有关键字值大于父节点的关键字值。

根据这个性质,对一个二叉树进行中序遍历,如果是单调递增的,则可以说明这个树是二叉搜索树。

二叉搜索树可以用栈结构来实现,并不一定要用递归

b树

https://www.cnblogs.com/mayjors/p/11144874.html

b树是一种多路平衡查找树,每一个节点最多包含m个子节点,m被成为b树的阶,m的大小取决于磁盘页的大小,b树主要用于文件系统以及部分数据库索引,例如mongodb最多有m个子节点,最少有m/2个子节点,m是b树的阶

每个节点有多个key,key数量比子节点少1(除叶子节点)

所有叶子节点都在同一层,并且是有序的

b树和二叉树的区别b树一个节点可以有多个子节点,而二叉树只能有两个

mysql使用b+树是因为可以减少io次数,二叉树最坏情况下io次数等于树的高度

b树是矮胖,二叉树是高瘦

如果一个页包含更多key,查询效率可能更快

b+树

b+树是b树的变种,具体如下:每个节点的key数量等于子节点数量,每个key不保存数据,只保存索引,所有数据存储在子节点上

所有叶子节点包含了全部的key

在最底层,每一个叶子节点指向下一个叶子节点的指针,形成了一个有序链表

b树和b+树的区别b+树节点不包含数据,所有可以拥有更多的key,所以更加矮胖,io次数更少

b+树一定会查找到叶子节点,查询性能稳定

支持范围查询

二叉树的遍历

前序遍历

先序遍历就是先访问根节点,在访问左节点,最后访问右节点

33f1af914aa7fb64bca1494b28382275.png

中序遍历

中序遍历就是先访问左节点,再访问根节点,最后访问右节点

a37c75e4a1173e2034d00e79a4d2a770.png

后序遍历

后序遍历就是先访问左节点,再访问右节点,最后访问根节点

08ae1544a4ada05b36831ff4b201e96c.png

二叉树遍历代码package main

import "fmt"

// 二叉树的数据结构

type TreeNode struct {

Data int

Left *TreeNode

Right *TreeNode

}

// 二叉树的实现

type Tree struct {

root *TreeNode

}

// 添加数据

func (self *Tree) Add(data int) {

var queue []*TreeNode

newNode := &TreeNode{Data:data}

if self.root == nil {

self.root = newNode

}else {

queue = append(queue, self.root)

for len(queue) != 0 {

cur := queue[0]

queue = append(queue[:0], queue[0+1:]...)

// 往右树添加

if data > cur.Data {

if cur.Right == nil {

cur.Right = newNode

} else {

queue = append(queue, cur.Right)

}

// 往左数添加

} else {

if cur.Left == nil {

cur.Left = newNode

} else {

queue = append(queue, cur.Left)

}

}

}

}

}

// 前序遍历 根 ---> 左 --->右

func (self *Tree )preorderTraverse(node *TreeNode) {

if node == nil {

return

} else {

fmt.Print(node.Data, " ")

self.preorderTraverse(node.Left)

self.preorderTraverse(node.Right)

}

}

// 中序遍历 左 ---> 根 --->右

func (self *Tree) inorderTraverse(node *TreeNode) {

if node == nil {

return

} else {

self.inorderTraverse(node.Left)

fmt.Print(node.Data, " ")

self.inorderTraverse(node.Right)

}

}

// 后序遍历 左 ----> 右 ---> 根

func (self *Tree) postTraverse(node *TreeNode) {

if node == nil {

return

} else {

self.postTraverse(node.Left)

self.postTraverse(node.Right)

fmt.Print(node.Data, " ")

}

}

func main() {

tree := &Tree{}

tree.Add(50)

tree.Add(45)

tree.Add(40)

tree.Add(48)

tree.Add(51)

tree.Add(61)

tree.Add(71)

fmt.Println("前序遍历")

tree.preorderTraverse(tree.root)

fmt.Println("")

fmt.Println("中序遍历")

tree.inorderTraverse(tree.root)

fmt.Println("")

fmt.Println("后续遍历")

tree.postTraverse(tree.root)

}

参考

说明: 以上图片来源于网络

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值