用JS实现栈队列二叉树遍历等操作

Posted 开到荼蘼223's

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JS实现栈队列二叉树遍历等操作相关的知识,希望对你有一定的参考价值。

栈主要体现在后进先出,在一端进行插入和删除的数据结构,表尾端称为栈顶(top),表头端称为栈底(bottom),因为栈限定在表尾进行插入或者删除,所以栈又被称为后进先出的线性表

// 栈的构造函数
function Stack(){
    var items = [];
    // 将元素送入栈,放置于数组的最后一位
    this.push = function(element){
        items.push(element);
    }
    // 弹出栈顶元素
    this.pop = function(element){
        return items.pop();
    }
    // 查看栈顶元素
    this.peek = function(){
        return items[items.length-1];
    }
    // 确定栈是否为空
    this.isAmpty = function(){
        return items.length == 0;
    }
    // 清空栈中所有内容
    this.clear = function(){
        items = [];
    }
    // 返回栈的长度
    this.size = function(){
        return items.length;
    }
    // 以字符串显示栈中所以有的内容
    this.print = function(){
        console.log(items.toString());
    }
}

队列 先进先出,只允许在一端插入,在另一端删除,插入的一端称为队尾,删除的一端称为队头

// 队列的构造函数
function Queue(){
    var items = [];
    // 将元素推入队列
    this.enqueue = function(ele){
        items.push(ele);
    }
    // 将队列中的第一个元素弹出
    this.dequeue = function(){
        return items.shift();
    }
    // 查看队列的第一个元素
    this.front = function(){
        return items[0];
    }
    // 确定队列是否为空
    this.isAmpty = function(){
        return items.length === 0;
    }
    this.size = function(){
        return items.length;
    }
    // 清空队列中所有内容
    this.clear = function(){
        items = [];
    }
    // 以字符串显示队列中所有内容
    this.print = function(){
        console.log(items.toString())
    }
}

  /* 击鼓传花的小游戏
   * @param  {Array} nameList 参与人员列表
   * @param  {Number} num      在循环中要被弹出的位置
   * @return {String}          返回赢家(也就是最后活下来的那个)
   */
  function hotPotato(nameList, num) {
    var queue = new Queue();  
    for (var i = 0; i < nameList.length; i++) {
      queue.enqueue(nameList[i]);
    }  
    var eliminated = '';  
    while (queue.size() > 1) {
      for (var i = 0; i < num; i++) {
        queue.enqueue(queue.dequeue());
      }
      eliminated = queue.dequeue();
      console.log(eliminated + " Get out!")
    }
    return queue.dequeue();
  }
  var nameList = ['小明', '小红', '小王', '小强']
  hotPotato(nameList,3);

二叉树 每个节点都最多有两个节点,分别为左子节点和右子节点,满足这个条件的树就是二叉树

构建二叉树:在js中以对象的方式存放二叉树中各个节点的值

遍历:不重复的访问二叉树中的每一个节点每一个节点

  • 前序遍历:root-left-right
  • 中序遍历:let-root-right
  • 后序遍历:right-left-root
var tree = {
    value: 1,
    left:{
       value: 4,
       left: {
           value: 6
       },
       right: {
           value: 9,
           left: {
               value: 15
           }
       }
    },
    right: {
        value: 35,
        left: {
            value: 30,
            right: {
                value: 45
            }
        }
    }
}

/**
 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
 * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
 * 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历列{4,7,2,1,5,3,8,6},
 * 则重建二叉树并返回。
 * 
 *   输入:  前序:[1,2,3,4,5,6,7],
 * 
 *           中序:[3,2,4,1,6,5,7]
   
    输出:
           层次遍历: [1,2,5,3,4,6,7]
 */
 class binaryTree {
    constructor(v,l,r){
        this.val = v;
        this.left = l;
        this.right = r
    }
}

/**
 * 已知前序序列、中序序列
 * @param {*} pre 表示前序遍历序列
 * @param {*} next 表示中序遍历序列
 */
function reConstructBinaryTree(pre,next) {	 
    // 递归出口
    if(pre.length == 0 || next.length == 0 || pre.length != next.length) {
        return null;
    }
    // 拿到根结点
    let root = new binaryTree(pre[0]);
    
    // 找的根结点在中序遍历中的位置
    let i = 0;
    while(next[i] != root.val) {
        i++;
    }
    //确定左子树前序遍历长度
    preLeft = new Array(i);
    //确定左子树中序遍历长度
    inLeft = new Array(i);
  
    //确定右子树前序遍历长度
    let preRight = new Array(next.length - i -1);
    //确定右子树中序遍历长度
    let inRight = new Array(next.length - i -1);
     
    // 遍历依次拿到左右子树  前中序遍历的值
    for(let j = 0 ; j<next.length ;j++) {
        if(j < i) {
            preLeft[j] = pre[j+1];
            inLeft[j] = next[j];
        }else if(j > i) {
            preRight[j-i-1] = pre[j];
            inRight[j-i-1] = next[j];
        }
    }
    // 递归
    root.left = reConstructBinaryTree(preLeft,inLeft);
    root.right = reConstructBinaryTree(preRight,inRight);
    return root;
}

var pre_arr = []  //存放前序遍历序列
var in_arr =[] //存放中序遍历序列
var post_arr = [] //存放后序遍历序列
var level_arr = [] //存放层次遍历序列

/**
 * D:访问根结点,L:遍历根结点的左子树,R:遍历根结点的右子树。
 * 前序遍历:DLR
 */
var preOrder = function(node){  
    if(node){
        pre_arr.push(node.val)
        preOrder(node.left)
        preOrder(node.right)
    }
}
/**
 * D:访问根结点,L:遍历根结点的左子树,R:遍历根结点的右子树。
 * 中序遍历:LDR
 */
var inOrder = function (node) {  
    if (node) {
     inOrder(node.left);  
     in_arr.push(node.val);
     inOrder(node.right);
    }
}
/**
 * D:访问根结点,L:遍历根结点的左子树,R:遍历根结点的右子树。
 * 后序遍历:LRD
 */
var postOrder = function (node) { 
    if (node) {
     postOrder(node.left);
     postOrder(node.right);  
     post_arr.push(node.val);
    }
}

/**
 * 广度优先遍历(层次遍历)
    广度优先遍历是从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。
*/
var levelOrderTraversal = function(node) { 
    if(!node) {  
     throw new Error('Empty Tree')
    } 
    var que = []
    que.push(node) 
    while(que.length !== 0) {
     node = que.shift()  
     level_arr.push(node.val) 
     if(node.left) que.push(node.left)  
     if(node.right) que.push(node.right)
    }
}
//测试
    a = [1,2,3,4,5,6,7];
	b = [3,2,4,1,6,5,7];
    root = reConstructBinaryTree(a,b);
    preOrder(root)
    console.log("前序序列是:"+pre_arr);
    inOrder(root)
    console.log("中序序列是:"+in_arr);
    postOrder(root)
    console.log("后序序列是:"+post_arr);
    levelOrderTraversal(root)
    console.log("层次序列是:"+level_arr);

以上是关于用JS实现栈队列二叉树遍历等操作的主要内容,如果未能解决你的问题,请参考以下文章

算法刷题-二叉树的锯齿形层序遍历用栈实现队列_栈设计买卖股票的最佳时机 IV

N日一篇——二叉树

N日一篇——二叉树

N日一篇——二叉树

二叉树遍历(先序,中序,后序,层序)递归和非递归形式

二叉树的三种遍历非递归实现(栈) 以及层序遍历(队列)(java)