IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode —— [94. 二叉树的中序遍历] -> 正文阅读

[数据结构与算法]LeetCode —— [94. 二叉树的中序遍历]

法一:迭代

?参考代码:力扣

自己写的思路:

所谓中序遍历指的是,输出的时候是左子树,root,右子树。

所以先一直遍历左子树,把遍历的node都存入stack中;然后让栈顶节点出栈,出栈的同时,把它的右子节点压入栈,相当于递归右子节点。因为是中序遍历,在栈顶节点的右子节点压栈之前,要处理出栈节点的节点值,将它输出。

不同的子树要做同样的事情,一样要先将它的左子节点不断压栈,然后再出栈,带出右子节点入栈。

? 别人的思路:

中序遍历的迭代实现
搞清楚概念后,怎么用栈去模拟递归遍历,并且是中序遍历呢?

递归遍历一棵树,如下图,会先递归节点A,再递归B,再递归D,一个个压入递归栈。

即,先不断地将左节点压入栈,我们写出这部分代码:

while (root) {
? ? stack.push(root);
? ? root = root.left;
}


DFS的访问顺序是:根节点、左子树、右子树,现在要访问已入栈的节点的右子树了。

并且是先访问『位于树的底部的』即『位于栈的顶部的』节点的右子树。

于是,让栈顶节点出栈,出栈的同时,把它的右子节点压入栈,相当于递归右子节点。

因为是中序遍历,在栈顶节点的右子节点压栈之前,要处理出栈节点的节点值,将它输出。

新入栈的右子节点(右子树),就是在递归它。和节点A、B、D的压栈一样,它们都是子树。

不同的子树要做同样的事情,一样要先将它的左子节点不断压栈,然后再出栈,带出右子节点入栈。

即栈顶出栈的过程,也要包含下面代码,可见下面代码重复了两次:

while (root) {
? ? stack.push(root);
? ? root = root.left;
}


其实这两个 while 循环,分别对应了下面的两次 inorder 调用,就是递归压栈:

inorder(root.left);
res.push(root.val);
inorder(root.right);

自己默写的

func inorderTraversal(root *TreeNode) []int {
	stack := []*TreeNode{}
	res := []int{}
	for root != nil {
		stack = append(stack, root)
		root = root.Left
	}
	for len(stack) != 0 {
		node := stack[len(stack)-1]
		stack = stack[0 : len(stack)-1]
		res = append(res, node.Val)
		node = node.Right
		for node != nil {
			stack = append(stack, node)
			node = node.Left
		}
	}
	return res
}

抄袭的:

func inorderTraversal(root *TreeNode) []int {
	res := []int{}
	stack := []*TreeNode{}

	for root != nil {
		stack = append(stack, root)
		root = root.Left
	}
	for len(stack) != 0 {
		node := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		res = append(res, node.Val)
		node = node.Right
		for node != nil {
			stack = append(stack, node)
			node = node.Left
		}
	}
	return res
}

法二:递归

参考链接:力扣

递归就是一种循环,一种自己调用自己的循环。

一道题你看能不能用递归实现,需要具备两个条件:

  • 问题可以分为多个重复的子问题,子问题仅存在数据规模的差距。
  • 存在终止条件。

所以根据条件,对于实现递归,只需要两步:

  1. 找出重复的子问题(递推公式)。
  2. 终止条件。

根据上面讲的实现递归的两步来找:

(1) 找出重复的子问题
中序遍历的顺序是:左子树、根、右子树。

对于左子树、右子树来说,也是同样的遍历顺序。

所以这个重复的子问题就是:先遍历左子树、再取根节点,最后遍历右子树。

inOrder(root.left)
print(root.val)
inOrder(root.right)


(2) 确定终止条件
和前序遍历相同,就是当前的节点为空,空的没啥好遍历的。

if root == None:
? ? return?


最重要的两点确定完了,那总的代码也就出来了。

func inorderTraversal(root *TreeNode) []int {
	res := []int{}
	inorder(root, &res)
	return res
}

func recursion(root *TreeNode, resource *[]int) {
	if root == nil {
		return
	}
	recursion(root.Left, resource)
	*resource = append(*resource, root.Val)
	recursion(root.Right, resource)
}

总程序:

package main // 声明 main 包,表明当前是一个可执行程序

//https://blog.csdn.net/u013837825/article/details/120857910
//https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/shou-hua-tu-jie-yong-zhan-mo-ni-zhong-xu-bian-li-z/
type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func inorderTraversal(root *TreeNode) []int {
	stack := []*TreeNode{}
	res := []int{}
	for root != nil {
		stack = append(stack, root)
		root = root.Left
	}
	for len(stack) != 0 {
		node := stack[len(stack)-1]
		stack = stack[0 : len(stack)-1]
		res = append(res, node.Val)
		node = node.Right
		for node != nil {
			stack = append(stack, node)
			node = node.Left
		}
	}
	return res
}
func inorderTraversal_recursion(root *TreeNode) []int {
	res := []int{}
	recursion(root, &res)
	return res

}
func recursion(root *TreeNode, resource *[]int) {
	if root == nil {
		return
	}
	recursion(root.Left, resource)
	*resource = append(*resource, root.Val)
	recursion(root.Right, resource)
}
func addNode(head *TreeNode, value int) *TreeNode {
	if head == nil {
		return &TreeNode{value, nil, nil}
	} else if value >= head.Val {
		head.Right = addNode(head.Right, value)
	} else {
		head.Left = addNode(head.Left, value)
	}
	return head
}

func main() { // main函数,是程序执行的入口
	root := TreeNode{Val: 1}
	root.Left = &TreeNode{Val: 2}
	root.Right = &TreeNode{Val: 3}
	root.Left.Left = &TreeNode{Val: 4}
	root.Left.Right = &TreeNode{Val: 5}
	root.Right.Left = &TreeNode{Val: 6}
	root.Right.Right = &TreeNode{Val: 7}
	root.Left.Left.Left = &TreeNode{Val: 8}
	root.Left.Right.Right = &TreeNode{Val: 9}
	root.Right.Right.Right = &TreeNode{Val: 10}
	//root := addNode(nil, 1)
	//addNode(root, 1)
	//addNode(root, 7)
	//addNode(root, 2)
	//addNode(root, 6)
	//addNode(root, 5)
	//addNode(root, 3)
	res := inorderTraversal_recursion(&root)
	println(res)

}

?自己默写的,没有提示,纯手工:

func inorderTraversal(root *TreeNode) []int {
    stack := []*TreeNode{}
    res := []int{}
    for root!=nil {
        stack = append(stack,root)
        root = root.left
    }
    for len(stack)>0 {
        node := stack[len(stack)-1]
        res = append(res,node.value)
        stack = stack[0:len(stack)-1]
        root = node.right
        for root!=nil {
            stack = append(stack,root)
            root = root.left
        }
    }
    return res
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:52:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:51:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码