javascript的数据结构快速学-栈和队列

准备学习《学习JavaScript数据结构与算法》,自己也开始做一写笔记来记录总结,本文也是仅针对实现方面的总结。

如果出现错误,请在评论中指出,我也好自己纠正自己的错误

author: thomaszhou

栈的实现

栈,其实就是一个数组,但是这是个非常特殊的数组,因为栈有个特性:先进后出,什么意思呢?看着下面的图来讲解。

原谅我是个灵魂画手

  • 栈只有一个开口,这个开口,是进口,也是出口

    • 我们从这个口添加数据,也从这个口取出数据
  • 栈的原则:先进后出

    • 我们依次添加1,2,3进入栈中,那我们取出的第一个值是3,第二个取出的值是2,第三个是1。那如果在取出2的时候,又添加一个数呢?大家可以模拟一下
  • 定义栈类和声明的方法

function Stack() {  //定义栈 的类
      var items = [];
      
      this.push = function(elem) {//添加元素
        return items.push(elem);
      };

      this.pop = function() {//弹出元素
        return items.pop();
      };

      this.print = function() { //输出
        console.log(items.toString());
      };
      
      this.size = function() {//输出栈的长度
        return items.length;
      };
      
      this.clear = function() {//将栈置为空
        return items = [];
      };
      
      this.peek = function() {//显示顶层元素
        return items[items.length-1]
      };
      
      this.isEmpty = function() { // 判断栈是否为空
        return items.length === 0;
      };
}
复制代码

栈的测试函数

(function demo1() {
  let stack1 = new Stack();  //创建栈
  stack1.push(1);
  stack1.push(2);
  stack1.push(3);
  stack1.push(4);
  stack1.print();
  console.log(stack1.pop());//4
  console.log(stack1.peek());// 3
  console.log(stack1.isEmpty());// false
  stack1.clear();
  console.log(stack1.isEmpty());// true
})();

复制代码
  • 栈的例子:十进制转换为任意进制
    function divideBy2(elem, base) {
      var str = '',
          temp = 0,
          arr = new Stack(),//创建栈
          baseStr = '0123456789ABCDEF';
      while (elem !== 0) {
        arr.push(Math.floor(elem % base));//容易漏掉Math.floor()就会造成结果为undefine;
        elem = Math.floor(elem / base);
        // 
        //console.log(elem);  测试debug
      }
      while (!arr.isempty()) {
        console.log(arr);
        str += baseStr[arr.pop()]; // 字符串也是数组,所有要用baseStr[]。而不能用baseStr()
      }
      return str;
    }
    
    console.log(divideBy2(7, 2));
复制代码

队列的实现

(1) 普通队列

  • 队列和栈的不同就在于:
    • 1、栈是先进后出,那就是push和pop方法
    • 2、队列是先进先出,那就是push和shift方法
  • 我们看啊,从右边进去,依次添加1,2,3,4,取出的第一个值是啥?是1,第二个,第三个第四个就是2,3,4.也就是说,我们添加一定是从右边进去,取出一定是从左边出去,也就是上面说的先进先出,先进去的,就先出来
	function Queue() {
	  let items = [];

	  this.enqueue = function(ele) {
	    items.push(ele);
		};
	  this.dequeue = function() {
	    return items.shift();
		};

	  this.front = function() {
	    return items[0];
		};
	  //	下面方法 同 栈
	  this.isEmpty = function() {
	    return items.length === 0;
		};

	  this.clear = function() {
	    items = [];
		};

	  this.size = function() {
	    return items.length;
	  };

          this.print = function() {
            console.log(items.toString());
          }
	}
复制代码

普通队列的测试函数:

	(function queueDemo() {
	  var queue = new Queue();
	  queue.enqueue(1);
	  queue.enqueue(2);
	  queue.enqueue(3);
	  queue.print();    //1,2,3
	  console.log(queue.dequeue()); //1
	  console.log(queue.isEmpty()); //false
	  console.log(queue.size());    //2
	  console.log(queue.front());   //2
	  queue.clear();
	  console.log(queue.size());  // 0
	})();
复制代码

(2) 优先队列

优先队列的核心在于设置优先级,队列的每个数据不是单一值,而是一个值和一个优先级id

  • 1、 采用构造函数,构造一个含有element和priority的实例
  • 2、 每次添加实例到队列中,按照优先级的先后插入到队列中(splice方法)
//	优先队列
	function PriorityQueue() {
	  let items = [];
	  function QueueElement(element, priority) {
	    this.element = element;
	    this.priority = priority;
		}

	  this.enqueue = function(element, priority) {
	    let ele = new QueueElement(element, priority);
	    if (this.isEmpty() === true) { // 队列为空,直接push
	      items.push(ele);
	    }else {
	      // 队列不为空,element的优先级priority小的在前面
              for (let i = 0; i < items.length; i++) {
                if (ele.priority < items[i].priority) {
                  items.splice(i, 0, ele);
		}else {
		//  element的优先级最低的情况-直接push到最后
                  items.push(ele);
		}
		break;
              }
	    }
	  };

      this.print = function() {
        for (let i = 0; i < items.length; i++) {
          console.log(`ele: ${items[i].element},prio: ${items[i].priority}`);
        }
      };

//		其他的方法和普通队列相同
      this.dequeue = function() {
        return items.shift();
      };

      this.front = function() {
        return items[0];
      };
     
      this.isEmpty = function() {
        return items.length === 0;
      };

      this.clear = function() {
        items = [];
      };

      this.size = function() {
        return items.length;
      };
	}
复制代码

优先队列测试函数:

(function priQueueDemo() {
  var queue = new PriorityQueue();
  queue.enqueue(1, 4);
  queue.enqueue(2, 7);
  queue.enqueue(3, 1);
  queue.print();
  
    //	ele: 3,prio: 1
	//  ele: 1,prio: 4
	//  ele: 2,prio: 7
  console.log(queue.dequeue());//QueueElement {element: 3, priority: 1}
  console.log(queue.isEmpty());//false
  console.log(queue.size());//2
  console.log(queue.front());//QueueElement {element: 1, priority: 4}
  queue.clear();
  console.log(queue.size());// 0
})();

复制代码

(3)循环队列

循环队列和普通队列的区别:普通队列和循环队列都是后面进一个,前面进一个.不同点就在于,循环队列是要将弹出的元素再返回到尾部再添加进去 核心代码就是queue.enqueue(queue.dequeue())

循环队列的应用-击鼓传花 击鼓传花的游戏都玩过,就是一堆人围一个圈,然后传递花,轮一圈,谁拿到花就淘汰谁(我们的例子是通过设置num来表示一轮传递几个人,算是一个规律性的击鼓传花,如果想实现真正的击鼓传花,那么就设置num为random,然后设置一个范围,就可以了,num = Math.floor(num * Math.random())

  • 所以也只是一个虚拟的游戏
function hotPotato (nameList, num) {
  let queue = new Queue(),
    len = nameList.length;

  for (let i = 0; i < len; i++) {
    queue.enqueue(nameList[i]);
  }
  while (queue.size() > 1) {// 队列最后剩下一个
    for (let i = 0; i < num; i++) {
      queue.enqueue(queue.dequeue());// 循环队列的核心
    }
    console.log(`${queue.dequeue()}被淘汰`);
  }
  console.log(`${queue.dequeue()}胜利`);//队列的最后一个值
}

let arr = ['thomas1', 'thomas2', 'thomas3', 'thomas4', 'thomas5'];
hotPotato(arr, 2);
//thomas3被淘汰
//thomas1被淘汰
//thomas5被淘汰
//thomas2被淘汰
//thomas4胜利


复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值