【数据结构与算法】递归转栈

前言

  • 以前学数据结构学的很盲目,特别是后面学递归dp感觉脑子完全不够用,好像自己完全不是这块料一样。后来群里吹牛以及找各种资料发现能用递归的都可以用栈实现,递归本质是让系统帮你维护个栈,而你不递归,那么就自己手动维护栈,这样就能达到同样效果。

简单例题

  • leecode 144. 二叉树的前序遍历
输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]

递归思路

var preorderTraversal = function(root) {
    let result = []
    var preOrderTraverseNode = (node) => {
        if(node) {
            // 先根节点
            result.push(node.val)
            // 然后遍历左子树
            preOrderTraverseNode(node.left)
            // 再遍历右子树
            preOrderTraverseNode(node.right)
        }
    }
    preOrderTraverseNode(root)
    return result
};
  • 这个递归模式是个套路写法,和深度优先一样:
let num=0//记录深度,上面那个题目不需要记录深度。
function depth(node){
	num++
	if(node.left){
		dosomething...
		depth(node.left)
	}
	if(node.right){
		dosomething...
		depth(node.right)
	}
	num--
	if(num===0){//出口,也可用来返回结果之类,上面那题结果在外面收集,不记录深度,有判断条件的递归不会无限递归。
		return 
	}
}
  • 还有个广度优先的写法,也是个套路,思路是维护一个队列:
function bfs(root){
	const q=[root]//根节点先入队
	while(q.length>0){
		const n=shift()//出队并读取
		n.children.forEach(child=>q.push(child))//孩子放入队列。
	}
}
  • 先中后序遍历也是套路:
function inorder(root){
	if(!root)return//左中右就是中序,先序是根左右,后续是左右根
	inorder(root.left)前
	root.val//中
	inorder(root.right)}

转栈思路

var preorderTraversal = function(root) {
    let result = []
    let stack=[]
    if(root)stack.push(root)//下面while循环里要从栈里拿出来
    while(stack.length!==0){
        let node= stack.pop()
        result.push(node.val)
        if(node.right){//右节点在前,左节点在后,这样先拿左节点的再拿出右节点的
            stack.push(node.right)
        }
        if(node.left){
            stack.push(node.left)
        }
    }
    return result
};
  • 本来递归的是节点,弄个栈自己维护,就变成把节点往栈里放,然后按顺序拿就行。
  • 先中后遍历转栈根上面思路一样。先序就是上面那个,中序需要先左子树,就是需要先把左子树的所有节点推到栈里。
const inorder=(root)=>{
	if(!root)return
	const stack=[]
	let p=root
	while(stack.length||p){
		while(p){
			stack.push(p)
			p=p.left
		}
		const n=stack.pop()
		console.log(n.val)
		p=n.right
	}
}
  • 后序遍历是先序的改版,把根拿个栈存起来,左右出完了出根。
const postorder=(root)=>{
	const stack=[root]
	const outputStack=[]
	while(stack.length){
		const n=stack.pop()
		outputStack.push(n)
		if(n.left)stack.push(n.left)
		if(n.right)stack.push(n.right)
		
	}
	while(outputStack.length){
		const n=outputStack.pop()
		console.log(n)
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章