javascript的數據結構快速學-棧和隊列

準備學習《學習JavaScript數據結構與算法》,本身也開始作一寫筆記來記錄總結,本文也是僅針對實現方面的總結。算法

若是出現錯誤,請在評論中指出,我也好本身糾正本身的錯誤數組

author: thomaszhoubash

棧的實現

棧,其實就是一個數組,可是這是個很是特殊的數組,由於棧有個特性:先進後出,什麼意思呢?看着下面的圖來說解。數據結構

原諒我是個靈魂畫手dom

  • 棧只有一個開口,這個開口,是進口,也是出口ide

    • 咱們從這個口添加數據,也從這個口取出數據
  • 棧的原則:先進後出函數

    • 咱們依次添加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) 普通隊列

  • 隊列和棧的不一樣就在於:
    • 一、棧是先進後出,那就是push和pop方法
    • 二、隊列是先進先出,那就是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());
          }
	}
複製代碼

普通隊列的測試函數:ui

(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

  • 一、 採用構造函數,構造一個含有element和priority的實例
  • 二、 每次添加實例到隊列中,按照優先級的前後插入到隊列中(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勝利


複製代碼
相關文章
相關標籤/搜索