《数据结构与算法》之二叉树

本文深入讲解了二叉树这一非线性数据结构,包括其基本概念、存储方式、操作方法及遍历算法,如前序、中序、后序和层次遍历。同时,提供了计算二叉树深度和宽度的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《数据结构与算法》之链表
《数据结构与算法》之链栈
《数据结构与算法》之队列
《数据结构与算法》之排序
《数据结构与算法》之二分查找

作为一个程序员,你肯定听说过二叉树,树是一种非线性结构,比前面所讲的栈、队列这种线性结构复杂很多。我们先通过一张图来了解一下二叉树这种结构
在这里插入图片描述
我们把没有父节点的节点叫做根节点,也就是图中的节点 E。A 节点就是 B 节点的父节点,B 节点是 A 节点的子节点。B、C、D 这三个节点的父节点是同一个节点,所以它们之间互称为兄弟节点。我们把没有子节点的节点叫做叶子节点或者叶节点,比如图中的 G、H、I、J、K、L 都是叶子节点。
树有三个比较重要的概念:高度深度,我们还是通过一张图来说明
在这里插入图片描述

二叉树的存储方式

二叉树的存储方式有两种,链式存储顺序存储
其中完全二叉树和满二叉树,合适使用顺序存储的方式

二叉树的操作

附上GitHubDemo地址

  • 向二叉查找树添加一个节点
    /// 向二叉查找树添加一个节点
    /// - Parameters:
    ///   - binaryTree: 二叉查找树
    ///   - value: 值
    /// - Returns: 二叉查找树
    class func addTreeNode(binaryTree: inout BinaryTree?, value: Int) -> BinaryTree {
        if binaryTree == nil  {
            //根节点不存在
            binaryTree = BinaryTree.init()
            binaryTree?.value = value
        }else if value < binaryTree!.value! {
            //值比节点的值小,插入左子树
            binaryTree?.leftNode = self.addTreeNode(binaryTree: &binaryTree!.leftNode, value: value)
        }else {
            //值比节点的值大,插入右子树
            binaryTree?.rightNode = self.addTreeNode(binaryTree: &binaryTree!.rightNode, value: value)
        }
        return binaryTree!
    }
  • 从二叉查找树中查找一个节点
    /// 从二叉查找树中查找一个节点
    /// - Parameters:
    ///   - binaryTree: 二叉查找树
    ///   - value: 值
    /// - Returns: 二叉查找树
    class func search(binaryTree: inout BinaryTree?, value: Int) -> BinaryTree? {
        if binaryTree == nil {
            return nil
        }else {
            if value < binaryTree!.value! {
                //要查找的值小于节点的值,从左子树继续查找
                return search(binaryTree: &binaryTree!.leftNode, value: value)
            }else if value > binaryTree!.value! {
                //要查找的值大于节点的值,从右子树继续查找
                return search(binaryTree: &binaryTree!.rightNode, value: value)
            }else {
                //要查找的值等于节点的值
                return binaryTree
            }
        }
        
    }
  • 前序遍历二叉树
    /// 前序遍历二叉树
    /// - Parameters:
    ///   - binaryTree: 二叉树
    ///   - handler: 返回遍历的节点
    class func firstErgodic(binaryTree: BinaryTree?, handler: (_ node: BinaryTree) -> ()) {
        if binaryTree != nil {
            handler(binaryTree!)
            self.firstErgodic(binaryTree: binaryTree?.leftNode, handler: handler)
            self.firstErgodic(binaryTree: binaryTree?.rightNode, handler: handler)
        }
    }
  • 中序遍历二叉树
    /// 中序遍历二叉树
    /// - Parameters:
    ///   - binaryTree: 二叉树
    ///   - handler: 返回遍历的节点
    class func middleErgodic(binaryTree: BinaryTree?, handler: (_ node: BinaryTree) -> ()) {
        if binaryTree != nil {
            self.middleErgodic(binaryTree: binaryTree?.leftNode, handler: handler)
            handler(binaryTree!)
            self.middleErgodic(binaryTree: binaryTree?.rightNode, handler: handler)
        }
    }
  • 后序遍历二叉树
    /// 后序遍历二叉树
    /// - Parameters:
    ///   - binaryTree: 二叉树
    ///   - handler: 返回遍历的节点
    class func lastErgodic(binaryTree: BinaryTree?, handler: (_ node: BinaryTree) -> ()) {
        if binaryTree != nil {
            self.lastErgodic(binaryTree: binaryTree?.leftNode, handler: handler)
            self.lastErgodic(binaryTree: binaryTree?.rightNode, handler: handler)
            handler(binaryTree!)
        }
    }
  • 层次遍历
    /// 层次遍历(广度优先)
    /// - Parameters:
    ///   - binaryTree: 二叉树
    ///   - handler: 返回遍历的节点
    class func levelErgodic(binaryTree: BinaryTree?, handler: (_ node: BinaryTree) -> ()) {
        if binaryTree == nil {
            return
        }
        
        var array = Array<BinaryTree>.init()
        array.append(binaryTree!)
        while array.count > 0 {
            let node = array.first
            handler(node!)
            //删除第一个节点
            array.removeFirst()
            if node?.leftNode != nil {
                array.append(node!.leftNode!)
            }
            
            if node?.rightNode != nil {
                array.append(node!.rightNode!)
            }
        }
    }
  • 二叉树的深度,深度从0开始
    /// 二叉树的深度,深度从0开始
    /// - Parameter binaryTree: 二叉树
    /// - Returns: 二叉树的深度
    class func depth(binaryTree: BinaryTree?) -> Int {
        if binaryTree == nil {
            return 0
        }
        
        if binaryTree?.leftNode == nil && binaryTree?.rightNode == nil {
            //如果节点的左右节点都为空,深度为0
            return 0
        }
        
        //左子树深度
        let leftDepth = self.depth(binaryTree: binaryTree?.leftNode)
        //右子树深度
        let rightDepth = self.depth(binaryTree: binaryTree?.rightNode)
        
        //二叉树的深度=max(左子树的深度,右子树的深度)+ 1
        return max(leftDepth, rightDepth) + 1
    }
  • 二叉树的宽度
    /// 二叉树的宽度
    /// - Parameter binaryTree: 二叉树
    /// - Returns: 二叉树的宽度
    class func width(binaryTree: BinaryTree?) -> Int {
        if binaryTree == nil {
            return 0
        }
        
        var array = Array<BinaryTree>.init()
        array.append(binaryTree!)
        //最大宽度,初始化为1(因为已经有根节点)
        var maxWidth = 1
        //当前宽度
        var curWidth = 1
        
        while array.count > 0 {
            curWidth = array.count
            for _ in 0 ..< curWidth {
                let node = array.first
                array.removeFirst()
                if node?.leftNode != nil {
                    array.append(node!.leftNode!)
                }
                
                if node?.rightNode != nil {
                    array.append(node!.rightNode!)
                }
            }
            maxWidth = max(maxWidth, array.count)
        }
        
        return maxWidth
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值