zoukankan      html  css  js  c++  java
  • 二叉树遍历及算法实现

    • 遍历定义

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

    • 遍历用途

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

    • 遍历方法

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

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

         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
    }
  • 相关阅读:
    类型转换
    with语句用法
    微软工具下载网址
    第2章信息系统服务管理
    声明变量
    管理机中录入485总表的操作方法
    任务 uitableview uiscrollview uiresponder
    如何去掉UITableViewController中的分隔线setSeparatorStyle
    NSRunLoop 概述和原理
    使用 Notifications
  • 原文地址:https://www.cnblogs.com/peteremperor/p/13990939.html
Copyright © 2011-2022 走看看