應用前端
隊列遵循先進後出(FIFO, 也稱爲先來先服務) 原則的. 平常有不少這樣場景: 排隊購票、銀行排隊等.
由對列的特性,銀行排隊爲例, 隊列應該包含以下基本操做:後端
class Queue { constructor() { // 隊列長度, 類數組 length this.count = 0 // 隊列中全部項 this.items = {} // 記錄對列頭, 類數組 index this.lowestCount = 0 } enqueue(ele) { this.items[this.count++] = ele } dequeue() { if (this.isEnpty()) { return undefined } const ele = this.items[this.lowestCount] delete this.items[this.lowestCount] this.lowestCount++ return ele } peek() { if (this.isEnpty()) { return } return this.items[this.lowestCount] } size() { /** * 當隊列爲非空時: * 1. count 是長度 * 2. lowestCount 是下標 * 二者關係應該 lowestCount = count - 1 */ return this.count - this.lowestCount } isEnpty() { return this.size() == 0 } clear() { this.items = {} this.lowestCount = 0 this.count = 0 } toString() { if (this.isEnpty()) { return '' } let objString = `${this.items[this.lowestCount]}` for (let i = this.lowestCount + 1; i < this.count; i++) { objString = `${objString}, ${this.items[i]}` } return objString } }
什麼是雙端隊列?數組
容許從前端(front)和後端(rear)添加元素, 遵循的原則先進先出或後進先出.
雙端隊列能夠理解爲就是棧(後進先出)和隊列(先進先出)的一種結合體. 既然是結合那麼相應的操做也支持隊列,棧的操做. 下面咱們定義一個Deque
數據結構
class Deque { constructor() { this.items = {} this.count = 0 this.lowestCount = 0 } addFront(ele) { if (this.isEmpty()) { this.items[this.count] = ele } else if (this.lowestCount > 0) { this.lowestCount -= 1 this.items[this.lowestCount] = ele } else { for (let i = this.count; i > 0; i--) { this.items[i] = this.items[i - 1] } this.items[0] = ele } this.count++ return ele } removeFront() { if (this.isEmpty()) { return } const delEle = this.items[this.lowestCount] delete this.items[this.lowestCount] this.lowestCount++ return delEle } addBack(ele) { this.items[this.count] = ele this.count++ } removeBack() { if (this.isEmpty()) { return } const delEle = this.items[this.count - 1] delete this.items[this.count - 1] this.count-- return delEle } peekFront() { if (this.isEmpty()) { return } return this.items[this.lowestCount] } peekBack() { if (this.isEmpty()) { return } return this.items[this.count - 1] } size() { return this.count - this.lowestCount } isEmpty() { return this.size() === 0 } clear() { this.items = {} this.count = 0 this.lowestCount = 0 } toString() { if (this.isEmpty()) { return '' } let objString = `${this.items[this.lowestCount]}` for (let i = this.lowestCount + 1; i < this.count; i++){ objString = `${objString}, ${this.items[i]}` } return objString } }
擊鼓傳花遊戲: 簡單描述就是一羣人圍成一個圈傳遞花,喊停的時花在誰手上就將被淘汰(每一個人均可能在前端,每一個參與者在隊列位置會不斷變化),最後只剩下一個時就是贏者. 更加詳細能夠自行查閱.dom
下面經過代碼實現:this
function hotPotato(elementsList, num) { // 建立一個容器 const queue = new Queue() const elimitatedList = [] // 把元素(參賽者)加入隊列中 for (let i = 0, len = elementsList.length; i < len; i++) { queue.enqueue(elementsList[i]) } /** * 擊鼓傳花 * 首先隊列規則: 先進先出 * 那麼在傳花過程當中,任何一個元素均可能是前端, 在傳花的過程當中應該就是前端位置不斷變化. * 當喊停的時(num 循環完), 也就是花落在誰手(誰在前端)則會被淘汰*(移除隊列) */ while (queue.size() > 1) { for (let j = 0; j < num; j++) { queue.enqueue(queue.dequeue()) } elimitatedList.push(queue.dequeue()) } return { winer: queue.dequeue(), elimitatedList } }
代碼運行以下:spa
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] console.log(hotPotato(arr, Math.ceil(Math.random() * 10))) // { winer: 5, elimitatedList: [4, 8, 2, 7, 3,10, 9, 1, 6]} console.log(hotPotato(arr, Math.ceil(Math.random() * 10))) // { winer: 5, elimitatedList: [4, 8, 2, 7, 3,10, 9, 1, 6]} console.log(hotPotato(arr, Math.ceil(Math.random() * 10))) // { winer: 8, elimitatedList: [10, 1, 3, 6, 2,9, 5, 7, 4]}
上一篇棧中也有涉及迴文的實現, 下面咱們經過雙端隊列來實現一樣的功能.code
function palindromeChecker(aString) { if (!aString || typeof aString !== 'string' || !aString.trim().length) { return false } const deque = new Deque() const lowerString = aString.toLowerCase().split(' ').join('') // 加入隊列 for (let i = 0; i < lowerString.length; i++) { deque.addBack(lowerString[i]) } let isEqual = true let firstChar = '' let lastChar = '' while (deque.size() > 1 && isEqual) { firstChar = deque.removeFront() lastChar = deque.removeBack() if (firstChar != lastChar) { isEqual = false } } return isEqual }
下面經過代碼演示下:blog
console.log(palindromeChecker('abcba')) // true 當前爲迴文
function generatePrintBinary(n) { var q = new Queue() q.enqueue('1') while (n-- > 0) { var s1 = q.peek() q.dequeue() console.log(s1) var s2 = s1 q.enqueue(s1 + '0') q.enqueue(s2 + '1') } } generatePrintBinary(5) // => 1 10 11 100 101