js实现按层次非递归遍历二叉树

定义二叉树的存储结构

class BiTNode{
    constructor(lchild,data,rchild){
        this.lchild=lchild;
        this.data=data;
        this.rchild=rchild;
    }
    setLchild(lchild){
        this.lchild = lchild;
    }
    setRchild(rchild){
        this.rchild = rchild;
    }
}

构造二叉树的代码

/**
 * 
 * @param {*string 先序二叉树字符串序列,其中空树用字符#表示 } s 
 * @returns 二叉树的根节点
 */
function CreateBiTree(s){ 
    //非递归建立二叉树
    //s="abc##de#g##f###";  //测试序列
    s = s.trim();
    let root=new BiTNode(null,s[0],null,null);
    let stack=[root];
    for(let i=1;i<s.length;i++){
        let biNode = new BiTNode(null,s[i],null,null);
        if(stack[stack.length-1].data!="#"){
            if(biNode.data!="#"){//如果为空则不添加
                stack[stack.length-1].setLchild(biNode);
            }
        }else{
            stack.pop();
            let cur=stack.pop();
            if(biNode.data!="#"){
                if(cur.data != "#"){
                    cur.setRchild(biNode);
                }else{
                    //空树不予许设置字树,出现则说明用户输入的字符序列错误
                    return null;
                }
            }
        }
        stack.push(biNode);
    }
    return root;
}

按层次遍历二叉树:用一个变量nextLastNode来保存下一层的最后一个结点。用队列来保存遍历过的结点,先判断刚出队列的结点(即curNode)其左右子树是否为空,不为空则进入队列,然后再判断当前结点是否为下一层的最后一个结点,如果是则更新nextLastNode,最后更新curNode;

/**
 * 按层次遍历二叉树,每遍历完一层二叉树 输出 '换一行'
 * @param {* BiTNode} root 
 */
function levelOrderTraversal(root) {
	    let queue = [];           //用队列来保存结点
	    let curNode = root;       //当前正在遍历的结点
	    let nextLastNode = root;  //指向下一层最后一个结点
	    while(curNode != null) {`在这里插入代码片`
	        alert(curNode.data);  //输出当前数据
	        if(curNode.lchild != null) {
	            queue.push(curNode.lchild);
	        }
	        if(curNode.rchild != null) {
	            queue.push(curNode.rchild);
	        }
	        if(curNode == nextLastNode) {
	            //如果右子树为null,则下一层最后一个结点的最后一个结点是当前结点的左子树,
	            //否则是下一层最后一个结点的最后一个结点是当前结点的右子树
	            nextLastNode = curNode.rchild == null ? curNode.lchild : curNode.rchild;
	            alert("换一行");
	        }
	        curNode = queue.shift();
	   }
}

后序遍历非递归二叉树:用栈来保存遍历后的结点,给入栈的结点添加一个标志位,用于标志结点的访问状态,该标志位true说明当前遍历的结点是该入栈结点的左子树那部分,反之则为右子树。

/**
 * 后序遍历非递归二叉树
 * @param {* 二叉树根结点} root 
 * @returns 保存遍历结果的数组
 */
function PostOrderTraverse(root){
    let stack=[];                   //保存遍历过得结点
    let isLeftChildTraverse = [];   //用于标志是否正在遍历左子树
    let curTreeNode = root;         //当前正在遍历的结点
    let list = [];                  //用于存放遍历结果
    while(stack.length > 0 || curTreeNode != null) {
        while(curTreeNode != null) {
            stack.push(curTreeNode);
            isLeftChildTraverse.push(true);
            curTreeNode = curTreeNode.lchild;
        }
        curTreeNode = stack[stack.length-1].rchild == null ? null : stack[stack.length-1].rchild;
        isLeftChildTraverse[isLeftChildTraverse.length-1] = false;
        while(curTreeNode == null && isLeftChildTraverse[isLeftChildTraverse.length-1] == false){
            list.push(stack.pop().data);
            isLeftChildTraverse.pop();
        }
    }
    // alert("list: "+list.join(","));
    return list;
}

求二叉树深度

/**
* 
* @param {*二叉树的根节点} root 
* @returns 二叉树的深度
*/
function TreeDepth(T) {
    let deep = 0;
    if(T){
        let leftdeep = TreeDepth(T.lchild);
        let rightdeep = TreeDepth(T.rchild);
        deep = leftdeep>=rightdeep?leftdeep+1:rightdeep+1;
    }
    return deep;
}

你可能感兴趣的:(算法题)