1. 程式人生 > >Javascript資料結構與演算法--棧的實現與用法

Javascript資料結構與演算法--棧的實現與用法

棧資料結構

棧是一種遵從後進先出(LIFO)原則的有序集合。新新增的或者待刪除的元素都儲存在棧的同一端,稱作棧頂,另一端就叫棧底。在棧裡,新元素都靠近棧頂,舊元素都接近棧底。

我們在生活中常能看到棧的例子。整齊堆起來的書,廚房堆起的盤子等

棧也被用在程式語言的編譯器和記憶體中儲存變數、方法呼叫等。

/**
 * 使用es6中的Class語法來編寫類:棧
 * 此棧使用陣列來儲存元素
 */
class Stack {
  constructor() {
    this.items = [];
  }

  /**
   * 新增一個(或幾個)新元素到棧頂
   * @param {*} element 新元素
   */
  push(element) {
    this.items.push(element)
  }

  /**
   * 移除棧頂的元素,同時返回被移除的元素
   */
  pop() {
    return this.items.pop()
  }

  /**
   * 返回棧頂的元素,不對棧做任何修改(這個方法不會移除棧頂的元素,僅僅返回它)
   */
  peek() {
    return this.items[this.items.length - 1]
  }

  /**
   * 如果棧裡沒有任何元素就返回true,否則返回false
   */
  isEmpty() {
    return this.items.length === 0
  }

  /**
   * 移除棧裡的所有元素
   */
  clear() {
    this.items = []
  }

  /**
   * 返回棧裡的元素個數。這個方法和陣列的length屬性很類似
   */
  size() {
    return this.items.length
  }

  /**
   * 返回以字串形式輸出的棧
   */
  toString() {
    return this.items.toString()
  }

  /**
   * 返回以陣列形式輸出的棧
   */
  toArray() {
    return this.items
  }

}

棧的用法

進位制轉換

更多詳情請檢視原始碼
在計算機裡所有的內容都是二進位制數字表示的(0和1),而我們生活中主要用到十進位制,還有16進位制等。那麼就需要進位制轉換。我們可以利用棧來實現轉換。

/**
 * 10進位制數轉換為其他16進位制以內進位制的數
 * @param {*} decNumber 需要轉換的數
 * @param {Int32Array} hex 進位制數
 */
function hexConverter(decNumber, hex) {
  let remStack = new Stack()
  let rem = 0
  let baseString = ''
  let digits = '0123456789ABCDEF' //進製取數

  if (hex < 2 || hex > 16) {
    return '只轉換大於二進位制小於十六進位制之間的進位制'
  }
  while (decNumber > 0) {
    rem = Math.floor(decNumber % hex) // 求模運算
    remStack.push(rem)
    decNumber = Math.floor(decNumber / hex) // 除運算
  }

  while (!remStack.isEmpty()) {
    baseString += digits[remStack.pop()] // 取出棧中的資料對應於進位制數的表示數
  }

  return baseString
}

迴文判斷

更多詳情請檢視原始碼
正讀反讀都相同的字元序列稱為迴文,例如“abccba”、“abcba”、“12321”、“123321”。
迴文判斷有很多種方法,在這裡,我們可以採用先入棧後出棧的方法,來比較入棧之前,和出棧之後兩個字串是否相同。
空字串到底是不是迴文呢,有點疑惑? 我這裡定義為不是迴文。

/**
 * 判斷字串是否為迴文
 * @param {String} str 要判斷的字串
 */
 function palindrome(str) {
  // 非string型別的 或者  空字串  直接判斷不是迴文
  if (typeof (str) !== 'string' || str.length === 0) {
    return false
  }

  let stack = new Stack()
  let oStr = str.toLocaleLowerCase()
  let nStr = ''

  for (let i = 0; i < str.length; i++) {
    stack.push(str[i])
  }

  while (!stack.isEmpty()) {
    nStr += stack.pop().toLocaleLowerCase()
  }

  if (nStr === oStr) {
    // return `輸入的字串【{$oStr}】是迴文`
    return true
  } else {
    // return `輸入的字串【{$oStr}】不是迴文`
    return false
  }
}

平衡括號

更多詳情請檢視原始碼
如果一個括號序列包含完整的左右括號對,則稱為平衡括號序列。如:"{[()]}","", "({})", "{()}"都是平衡括號,而"{()[]", ")"則不是平衡括號。

括號只有三種()/[]/{},每種分別有左右括號。我們可以這樣操作:遇到左括號,左括號入棧,遇到右括號,取出棧中最後一個括號來比對的方式來判斷是否相等平衡。

/**
 * 判斷括號序列是否平衡,空序列也算是平衡
 * @param {String} brackets 括號序列
 */
function balanceBracket(brackets) {
  if (typeof (brackets) !== 'string') {
    return false
  }

  let left = '([{'
  let right = ')]}'
  let num = 0 // 括號的對數
  let stack = new Stack()

  for (let i = 0; i < brackets.length; i++) {
    if (right.indexOf(brackets[0]) > -1) {
      return false
    }
    if (left.indexOf(brackets[i]) > -1) {
      stack.push(brackets[i])
      num++
    } else {
      if (right.indexOf(brackets[i]) > -1) {
        let topBracket = stack.pop()
        let rightSort = right.indexOf(brackets[i])
        let leftSort = left.indexOf(topBracket)

        if (rightSort !== leftSort) {
          return false
        }
      }
    }
  }
  return `是平衡括號序列。有${num}對括號`
}

漢諾塔

更多詳情請檢視原始碼
有三根相鄰的柱子,標號為A,B,C。A柱子上從下到上按金字塔狀疊放著n個不同大小的圓盤,要把所有圓盤移動到B柱子上。
要求:

  1. 每次只能移動一個圓盤。
  2. 每根柱子上的圓盤,下面的都比上面的大。

問題:
請問至少需要移動多少次圓盤?每次移動的步驟是怎樣的?

let num = 0 // 記錄移動的次數

/**
 * 記錄圓盤移動的過程
 *
 * 這裡的思路,一直在迴圈做一件事情。
 * 把原始柱子上的圓盤分為兩部分,最大和其它。
 * 第一回合,將其它移動到輔助柱子上,將最大的移動到目標柱子上,再將其它移動到目標柱子上
 * 第二回合,將其它移動到輔助柱子上,將最大的移動到目標柱子上,再將其它移動到目標柱子上
 * ...
 * 第2 ** n - 1回合,將其它移動到輔助柱子上,將最大的移動到目標柱子上,再將其它移動到目標柱子上
 *
 * 但是,這裡源柱子、輔助柱子和目標柱子會隨著其它盤而變動。
 * 其它盤在哪個柱子上,哪根柱子就是源柱子。

 * @param {Int32Array} plates 圓盤個數
 * @param {Array} source 源柱子
 * @param {Array} helper 輔助柱子
 * @param {Array} dest 目的地柱子
 * @param {String} sourceName 源柱子的名字
 * @param {String} helperName 輔助柱子的名字
 * @param {String} destName 目的地柱子的名字
 * @param {Array} moves 步驟儲存器,儲存每一步的流程
 */
function moveOfHanoi(
  plates,
  source,
  helper,
  dest,
  sourceName,
  helperName,
  destName,
  moves = []
) {
  if (plates <= 0) {
    return moves
  } else if (plates === 1) {
    // 彈出源柱子上剩下的最大圓盤,並將其壓入目標柱子
    dest.push(source.pop())
    num++
    let sourceArr = source.toString()
    let helperArr = helper.toString()
    let destArr = dest.toString()
    let movestr = `第 ${num} 步,將圓盤 ${plates} 從 ${sourceName} 移至 ${destName}; ${sourceName}: [${sourceArr}],${helperName}: [${helperArr}],${destName}: [${destArr}]`
    moves.push(movestr)
  } else {
    moveOfHanoi(
      plates - 1,
      source,
      dest,
      helper,
      sourceName,
      destName,
      helperName,
      moves
    )

    // 彈出源柱子上剩下的最大圓盤,並將其壓入目標柱子
    dest.push(source.pop())
    num++
    let sourceArr = source.toString()
    let helperArr = helper.toString()
    let destArr = dest.toString()
    let movestr = `第 ${num} 步,將圓盤 ${plates} 從 ${sourceName} 移至 ${destName}; ${sourceName}: [${sourceArr}],${helperName}: [${helperArr}],${destName}: [${destArr}]`
    moves.push(movestr)

    moveOfHanoi(
      plates - 1,
      helper,
      source,
      dest,
      helperName,
      sourceName,
      destName,
      moves
    )
  }
  return moves
}

/**
 * 漢諾塔
 * 記錄每一次圓盤移動的動作。從${源柱子}到${目標柱子}
 * @param {Int32Array} plates 圓盤的個數
 * @param {String} sourceName 源柱子的名稱
 * @param {String} helperName 輔助柱子的名稱
 * @param {String} destName 目標柱子的名稱
 */
function hanoiStackArray(plates, sourceName, helperName, destName) {
  let source = new Stack()
  let helper = new Stack()
  let dest = new Stack()

  for (let i = plates; i > 0; i--) {
    source.push(i)
  }
  num = 0
  return moveOfHanoi(
    plates,
    source,
    helper,
    dest,
    sourceName,
    helperName,
    destName
  )
}

[完]

相關推薦

JavaScript資料結構演算法 ---

概念:表頭進行插入和刪除操作的線性表 核心思想:先進後出 作用:在程式語言的編譯器和記憶體中儲存變數、方法呼叫 操作方法:1)push() 進棧,即向棧裡新增元素                   2)pop() 出棧,即把元素從棧中刪除            

(考研必看)最全資料結構排序演算法效能分析比較!!!

資料結構所有排序演算法效能分析與比較 轉載請標明出處weixin_44254963或璇小姐 通過對資料結構的學習,我發現數據結構中各種排序演算法的排序方法,過程,以及時間效能,空間效能都比較容易混淆,現就這些情況做如下總結,希望對大家有所幫助。 起泡排序(氣泡排序) 首先取第一個

資料結構演算法--

順序棧 三個基本屬性 棧的儲存資料data 棧的最大儲存量maxSize 棧頂top Python實現 # Python 2.7 class sqStack(object): # 初始化 def __init__(self,

JS資料結構演算法 ---

概念:表頭進行插入和刪除操作的線性表 核心思想:先進後出 作用:在程式語言的編譯器和記憶體中儲存變數、方法呼叫 操作方法:1)push() 進棧,即向棧裡新增元素                 &n

資料結構——使用Java實現【括號匹配】

給定一個只包括 '(',')','{','}','[',']'的字串,判斷字串是否有效。 有效字串需滿足: 左括號必須用相同型別的右括號閉合。 左括號必須以正確的順序閉合。 注意空字串可被認為是有效字串。 參考leetcode.com或leetcode-cn.com

資料結構用順序實現R進位制轉換

#include<stdio.h> #define MAXSIZE 500 typedef struct{ int *base; int *top; int stacksize; }Sqstack; int Initstack(Sqstack &S)

JavaScript資料結構演算法

前言 在過去的幾年中,得益於Node.js的興起,JavaScript越來越廣泛地用於伺服器端程式設計。鑑於JavaScript語言已經走出了瀏覽器,程式設計師發現他們需要更多傳統語言(比如C++和Java)提供的工具。這些工具包括傳統的資料結構(如連結串列,棧,佇列,圖等),也包括傳統的排序和查詢演算法。

資料結構之用實現迷宮問題(dfs)

給一個n*n的方格,讓你求從左上角到所給一點的任意一條路徑並輸出 該題用到dfs,以下是對dfs的簡要解析  :詳解請參見 傳送門 dfs是一種用於遍歷或搜尋樹或圖的演算法。 沿著樹的深度遍歷樹的節點,儘可能深的搜尋樹的分支。當節點v的所在邊都己被探尋過或者在搜尋時結點不

JavaScript資料結構之隊互搏

今天稍微停下前進的腳步,來看下隊棧的左右互搏術。 前兩天學習了佇列和棧以後,今天就可以試著來用兩個棧實現佇列的功能 或者 用兩個佇列來實現棧的功能。 資料結構之---棧實現佇列 1. 用兩個棧實現一個佇列 1.1 題目分析 棧是先進後出,佇列是先進先出,但可以用兩個棧來模擬一個佇列的功能,來實現

【Java資料結構】用實現字尾表示式求值

今天在學資料結構,自己擼一段用棧來實現字尾表示式求值的程式碼,能改進的地方還有很多,在此先mark一下 package StackPractice; import java.util.Scanner; import java.util.Stack; im

資料結構——————排序演算法程式碼實現(未完待續......)

排序演算法 插入排序 折半插入排序 希爾排序 氣泡排序 快速排序 簡單選擇排序 堆排序 歸併排序(未完成) 基數排序(未完成) #include<bits/stdc++.h> using namespace

資料結構】利用實現表示式求值

前言 java實現,利用int型別儲存運算元,完善了char類型範圍太小的問題,利用遞迴,完善了括號巢狀使用的問題。 執行結果截圖 程式碼實現: import java.util.Arrays; import java.util.Scanner; public

挑戰資料結構演算法——的push、pop序列

題目來源“資料結構與演算法面試題80道”。在此給出我的解法,如你有更好的解法,歡迎留言。 問題分析:本題考查棧的基本操作,棧是一種“先進後出”的資料結構。判斷一個序列是否是棧的pop序列是

經典資料結構演算法-Java實現-附原始碼(可下載)

閒暇之餘,將自己之前敲過的資料結構與演算法程式碼整理了一下,最後放在一個工程下面:具體分類:剛看了下專案目錄,少了排序分類介紹圖,在這裡補上(此圖來源於網上)最後,程式碼比較多,只展示下排序演算法的程式碼。package com.lzz.algorithm.sorting;

資料結構演算法(Golang實現)(30)查詢演算法-2-3-4樹和普通紅黑樹

文章首發於 閱讀更友好的GitBook。 2-3-4樹和普通紅黑樹 某些教程不區分普通紅黑樹和左傾紅黑樹的區別,直接將左傾紅黑樹拿來教學,並且稱其為紅黑樹,因為左傾紅黑樹與普通的紅黑樹相比,實現起來較為簡單,容易教學。在這裡,我們區分開左傾紅黑樹和普通紅黑樹。 紅黑樹是一種近似平衡的二叉查詢樹,從2-3樹或2

資料結構演算法(Golang實現)(25)排序演算法-快速排序

快速排序 快速排序是一種分治策略的排序演算法,是由英國電腦科學家Tony Hoare發明的, 該演算法被髮布在1961年的Communications of the ACM 國際計算機學會月刊。 注:ACM = Association for Computing Machinery,國際計算機學會,世界性的計

Javascript資料結構演算法--實現用法

棧資料結構 棧是一種遵從後進先出(LIFO)原則的有序集合。新新增的或者待刪除的元素都儲存在棧的同一端,稱作棧頂,另一端就叫棧底。在棧裡,新元素都靠近棧頂,舊元素都接近棧底。 我們在生活中常能看到棧的例子。整齊堆起來的書,廚房堆起的盤子等 棧也被用在程式語言的編譯器和記憶體中儲存變數、方法呼叫等。 /**

為什麼我要放棄javaScript資料結構演算法(第三章)——

有兩種結構類似於陣列,但在新增和刪除元素時更加可控,它們就是棧和佇列。 第三章 棧 棧資料結構 棧是一種遵循後進先出(LIFO)原則的有序集合。新新增的或待刪除的元素都儲存在棧的同一端,稱為棧頂,另一端就叫做棧底。在棧裡, 新元素都靠近棧頂,舊元素都接近棧底。 棧也被用在程式語言的編譯器和記憶體中儲存

javascript資料結構演算法筆記(一):

javascript資料結構與演算法筆記(一):棧 一:簡介 二:ES6版Stack類(陣列) 三:ES版Stack類私有屬性的封裝 1.偽私有屬性封裝 2.真私有屬性封裝

python演算法資料結構002--利用列表實現的功能

class Statck(object): """ 棧:後進先出的資料結構 利用列表實現棧的基本功能。 """ def __init__(self): self.items=[] def