• 二叉树的重建


    已知二叉树前序遍历和中序遍历的结果,重建二叉树

    解决思路:

    • 前序遍历的结果中根节点在左右孩子的前面,左孩子在右孩子前面;中序遍历的结果中根节点在左右孩子的中间,中序遍历可以找出根节点的左子树和右子树,前序遍历的第一个节点是根节点,根据这些特性可以递归的重建二叉树

    例如 pre=[1,2,4,7,3,5,6,8] mid=[4,7,2,1,5,3,8,6]

    1. 1作为根节点,左子树[4,7,2] 右子树[5,3,8,6]

    2. 左子树[4,7,2]中由于前序遍历结果2在前面,所以2位左子树根节点;同理3是右子树根节点;因此2有左子树[4,7]没右子树,3有左子树5,右子树[8,6]

    3. [4,7]由于前序遍历中4在前面,所以4是根节点,4右子树为[7];同理[8,6]中6为根节点,[8]是左子树

    4. 最终二叉树为[1,2,3,4,null,5,6,null,7,null,null,null,null,8]

           1
          2 3
         4 5 6
          7 8
      
    • 采用排序二叉树中序遍历为有序数组的特性

    1.思路一

    func main() {
    	pre := []int{1, 2, 4, 7, 3, 5, 6, 8} // 根节点
    	mid := []int{4, 7, 2, 1, 5, 3, 8, 6}
    
    	root := new(node)
    	reBuildTree(root, pre, mid)
    
    	// 前序遍历
    	preV(root)
    	fmt.Println()
    	// 中序遍历
    	midV(root)
    	fmt.Println()
    }
    
    
    // 重建左子树
    func reBuildTree(root *node, pre, mid []int) {
    	if len(pre) == 0 {
    		return
    	}
    
    	// 确定根节点
    	root.val = pre[0]
    	var idx int
    	for ; mid[idx] != pre[0]; idx++ {
    	}
    	//左子树
    	leftMid := mid[:idx]
    	leftPre := pre[1:len(leftMid)+1]
    	if len(leftPre) > 0 {
    		n := new(node)
    		root.left = n
    		reBuildTree(n, leftPre, leftMid)
    	}
    
    	// 右子树
    	rightMid := mid[idx+1:]
    	rightPre := pre[len(leftMid)+1:]
    	if len(rightPre) > 0 {
    		n := new(node)
    		root.right = n
    		reBuildTree(n, rightPre, rightMid)
    	}
    }
    
    // 前序遍历
    func preV(root *node) {
    	if root != nil {
    		fmt.Print(root.val)
    		preV(root.left)
    		preV(root.right)
    	}
    
    }
    
    // 中序遍历
    func midV(root *node) {
    	if root != nil {
    		midV(root.left)
    		fmt.Print(root.val)
    		midV(root.right)
    	}
    
    }
    

    output:

    12473568
    47215386
    

    2.思路二

    func main() {
    	pre := []int{1, 2, 4, 7, 3, 5, 6, 8} // 根节点
    	mid := []int{4, 7, 2, 1, 5, 3, 8, 6}
    
    	// 排序二叉树,中序遍历顺序递增
    	sortM := make(map[int]int, len(mid))
    	for i, v := range mid {
    		sortM[v] = i
    	}
    	root := new(node)
    	root.val = pre[0]
    	// 按照前序遍历的顺序插入节点
    	for _, v := range pre {
    		insert(v, root, sortM)
    	}
    
    	// 前序遍历
    	preV(root)
    	fmt.Println()
    	// 中序遍历
    	midV(root)
    	fmt.Println()
    }
    
    
    func insert(data int, root *node, sortM map[int]int) {
    	if sortM[data] < sortM[root.val] {
    		if root.left != nil {
    			insert(data, root.left, sortM)
    		} else {
    			root.left = &node{val: data}
    			return
    		}
    	} else {
    		if root.right != nil {
    			insert(data, root.right, sortM)
    		} else {
    			root.right = &node{val: data}
    		}
    	}
    
    }
    

    output:

    12473568
    47215386
  • 相关阅读:
    动态展示图片
    vue 字符串长度控制显示的字数超出显示省略号
    ivew-admin 校验 自定义验证表单多层嵌套
    ivew 【provide/inject] 页面刷新实现reload
    vue-ivew input 框 回车搜索功能
    php中二维数组如何使用
    页面图片按钮案例
    html页面插入flash代码
    js动态设置输入框字体/颜色
    php如何判断是手机访问还是电脑访问
  • 原文地址:https://www.cnblogs.com/fwdqxl/p/10049510.html
Copyright © 2020-2023  润新知