• 二叉树遍历及算法实现


    • 遍历定义

    指按某条搜索路线遍访每个结点且不重复(又称周游)。

    • 遍历用途

    它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心。 

    • 遍历方法

    牢记一种约定,对每个结点的查看都是“先左后右”

    限定先左后右,树的遍历有三种实现方案:

         DLR                 LDR                LRD

    ()序遍历        ()序遍历        ()序遍历

     

    DLR — 先序遍历,即先根再左再右

    LDR — 中序遍历,即先左再根再右

    LRD — 后序遍历,即先左再右再根

    注:“先、中、后”的意思是指访问的结点D是先于子树出现还是后于子树出现。

    从递归的角度看,这三种算法是完全相同的,或者说这三种遍历算法的访问路径是相同的,只是访问结点的时机不同。

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type BinaryNode struct {
        Data   interface{} //数据
        lChild *BinaryNode //左子树
        rChild *BinaryNode //右子树
    }
    
    //创建二叉树
    func (node *BinaryNode) Create() {
        node = new(BinaryNode)
    }
    
    //先序遍历
    func (node *BinaryNode) PreOrder() {
        if node == nil {
            return
        }
        //DLR — 先序遍历,即先根再左再右
        fmt.Println(node.Data)
    
        //递归遍历左子树
        node.lChild.PreOrder()
        //递归遍历右子树
        node.rChild.PreOrder()
    
    }
    
    //中序遍历
    func (node *BinaryNode) MidOrder() {
        if node == nil {
            return
        }
    
        //LDR — 中序遍历,即先左再根再右
        //递归遍历左子树
        node.lChild.MidOrder()
        //打印数据
        fmt.Println(node.Data)
        //递归遍历右子树
        node.rChild.MidOrder()
    
    }
    
    //后序遍历
    func (node *BinaryNode) RearOrder() {
        if node == nil {
            return
        }
    
        //LRD — 后序遍历,即先左再右再根
        //递归遍历左子树
        node.lChild.RearOrder()
        //递归遍历右子树
        node.rChild.RearOrder()
        //打印数据
        fmt.Println(node.Data)
    }
    
    //二叉树高度 深度
    func (node *BinaryNode) TreeHeight() int {
        if node == nil {
            return 0
        }
        //进入下一层遍历
        lh := node.lChild.TreeHeight()
        rh := node.rChild.TreeHeight()
        if lh > rh {
            lh++
            return lh
        } else {
            rh++
            return rh
        }
    
    }
    
    //二叉树叶子节点个数
    //叶子节点是没有后继的节点
    func (node *BinaryNode) LeafCount(num *int) {
        if node == nil {
            return
        }
        //判断没有后继的节点为叶子节点
        if node.lChild == nil && node.rChild == nil {
            (*num)++
        }
        node.lChild.LeafCount(num)
        node.rChild.LeafCount(num)
    }
    
    //二叉树数据查找
    func (node *BinaryNode) Search(Data interface{}) {
        if node == nil {
            return
        }
    
        //== 不支持slice 和 map
        //reflect.DeepEqual()
        if reflect.TypeOf(node.Data) == reflect.TypeOf(Data) && node.Data == Data {
            fmt.Println("找到数据", node.Data)
            return
        }
        node.lChild.Search(Data)
        node.rChild.Search(Data)
    }
    
    //二叉树销毁
    func (node *BinaryNode) Destroy() {
        if node == nil {
            return
        }
    
        node.lChild.Destroy()
        node.lChild = nil
        node.rChild.Destroy()
        node.rChild = nil
        node.Data = nil
    
    }
    
    //二叉树反转
    //如果想反转二叉树 二叉树必须是一个满二叉树
    func (node *BinaryNode) Reverse() {
        if node == nil {
            return
        }
    
        //交换节点  多重赋值
        node.lChild, node.rChild = node.rChild, node.lChild
    
        node.lChild.Reverse()
        node.rChild.Reverse()
    
    }
    
    //二叉树拷贝
    func (node *BinaryNode) Copy() *BinaryNode {
        if node == nil {
            return nil
        }
        lChild:=node.lChild.Copy()
        rChild:=node.rChild.Copy()
    
        //创建写节点 拷贝数据
        newNode:=new(BinaryNode)
        newNode.Data=node.Data
        newNode.lChild=lChild
        newNode.rChild=rChild
        return newNode
    }
  • 相关阅读:
    Vulnhub_DC4 记录
    文件上传(解析)漏洞
    开源情报搜集
    Vulnhub_DC3 记录
    “恶意”利用IPC$
    Vulnhub_DC2 记录
    Vulnhub_DC1 记录
    合天网安实验室 渗透测试项目二
    合天网安实验室 渗透测试项目一
    编程如写作
  • 原文地址:https://www.cnblogs.com/peteremperor/p/13990939.html
Copyright © 2020-2023  润新知