JavaScript的資料結構與演算法(一)——棧和佇列

weixin_34148456發表於2017-02-18

1、棧

棧是一種遵從後進先出(LIFO)原則的有序集合。新新增的或待刪除的元素都儲存在棧的末尾。稱作棧頂,另一端就叫棧底。在棧裡,新元素都靠近棧頂,舊元素都靠近棧底。現在通過陣列的方法來實現棧,程式碼如下:

function Stack() {
  var items = [];
  this.push = function(element){//新增一個(或幾個)新元素到棧頂
    items.push(element);
  };
  this.pop = function(){//移除棧頂的元素,同時返回被移除元素
    return items.pop();
  };
  this.peek = function(){//返回棧頂的元素,但並不對棧做任何修改
    return items[items.length-1];
  };
  this.isEmpty = function(){//如果棧內沒有任何元素就返回true,否則返回false
    return items.length == 0;
  };
  this.size = function(){//返回棧裡的元素個數
    return items.length;
  };
  this.clear = function(){//移除棧裡的所有元素
    items = [];
  };
  this.print = function(){//列印
    console.log(items.toString());
  };
  this.toString = function(){
    return items.toString();
  };
}

下面是一個小演算法題,可以視為棧的綜合利用,如何將10進位制數字轉成2進位制數字:

function divideBy2(decNumber){
  var remStack = new Stack(),
  rem,
  binaryString = "";

  while(decNumber > 0){
    rem = Math.floor(decNumber % 2);
    remStack.push(rem);
    decNumber = Math.floor(decNumber / 2);
  }
  while(!remStack.isEmpty()){
    binaryString += remStack.pop().toString();//餘數除完翻轉過來就是2進位制數
  }
  return binaryString;
}

升級版, 如何將10進位制數字轉成任意進位制數字,程式碼如下:

function baseConverter(decNumber,base){
  var remStack = new Stack(),
  rem,
  baseString = "",
  digits = "0123456789ABCDEF";

  while(decNumber > 0){
    rem = Math.floor(decNumber % base);
    remStack.push(rem);
    decNumber = Math.floor(decNumber / base);
  }
  while(!remStack.isEmpty()){
    baseString += digits[remStack.pop()];
  }
  return baseString;
} 
baseConverter(100345,2) // "11000011111111001"
baseConverter(100345,8) //"303771"
baseConverter(100345,16) // "187F9"   

2、佇列

佇列遵循的是FIFO(先進先出)的原則的一組有序的項。佇列從尾部新增新元素,並從頂部移除元素,最新新增的元素必須排列在佇列的末尾。

function Queue() {
  var items = [];
  this.enqueue = function(element){//向佇列尾部新增一個(或是多個)元素
    items.push(element);
  };
  this.dequeue = function(){//移除佇列的第一個元素,並返回被移除的元素
    return items.shift();
  };
  this.front = function(){//返回佇列的第一個元素——最先被新增的,也將是最先被移除的元素。佇列不做任何變動。(不移除元素,只返回元素資訊。與stack的peek方法類似)
    return items[0];
  };
  this.isEmpty = function(){//如果佇列內沒有任何元素就返回true,否則返回false
    return items.length == 0;
  };
  this.clear = function(){//移除佇列裡的所有元素
    items = [];
  };
  this.size = function(){//返回佇列裡的元素個數
    return items.length;
  };
  this.print = function(){//列印                                                                                                                                                                                                                             
    console.log(items.toString());
  };
 }
2.1、優先佇列

指佇列元素的新增和移除是基於優先順序的。實現一個優先佇列,有兩種選項:設定優先順序,然後再正確的位置新增元素;或者用入隊操作新增元素,然後按照優先順序移除他們。下例將會在正確的位置新增元素,如下:

function PriorityQueue(){
  var items = [];
  function QueueElement(element, priority){
    this.element = element;
    this.priority = priority;
  }
  this.enqueue = function(element, priority){
    var queueElement = new QueueElement(element, priority);
    if(this.isEmpty()){
      items.push(queueElement);
    }else{
      var added = false;
      for(var i = 0; i < items.length; i++){
          if(queueElement.priority < items[i].priority){
            items.splice(i,0,queueElement);
            added = true;
            break;
          }
      }
    } 
    if(!added){
      items.push(queueElement);
    }
  }
  this.isEmpty = function(){
    return items.length == 0;
  }
  this.print = function(){
    console.log(items);
  }
}
2.2、迴圈佇列——擊鼓傳花

擊鼓傳花遊戲,在這個遊戲中,孩子們圍成一個圓圈,把花盡快的傳遞給旁邊的人。某一時刻傳花停止,這個時候花落在誰手裡,誰就退出圓圈結束遊戲。重複這個過程,直到只剩下一個孩子。例子如下:

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+"在遊戲中淘汰了。");
  }
  return queue.dequeue();
}
var names = ["a","b","c","d","e"];
var winner = hotPotato(names,7);
console.log("勝利者"+winner);
//c在遊戲中淘汰了。
//b在遊戲中淘汰了。
//e在遊戲中淘汰了。
//d在遊戲中淘汰了。
//勝利者a

相關文章