Pythonアルゴリズム実践シリーズ: スタック

Pythonアルゴリズム実践シリーズ: スタック

スタックは、特別な順序付けがされたテーブルです。挿入および削除操作はスタックの先頭で実行され、先入れ後出しおよび後入れ先出しのルールに従って動作します。

下の図に示すように

たとえば、銃のマガジンでは、最初にマガジンに入れられた弾丸が発射されるときに最後に発射され、最後にマガジンに入れられた弾丸が発射されるときに最初に発射されます。

スタックインターフェース

スタックを作成する場合、スタックを操作するために次のインターフェースが必要です。

スタックには上記のインターフェースが必要であることがわかっているので、Python ではリストはスタックに似ており、次のインターフェースを提供します。

Python でスタック インターフェイスを使用する例:

  1. # スタックを作成する
  2.  
  3. [1]において: s = []
  4.  
  5. # スタックに要素を追加する
  6.  
  7. [2]では: s.append(1)
  8.  
  9. [3]では
  10.  
  11. アウト[3]:[1]
  12.  
  13. # スタックから要素を削除する
  14.  
  15. [4]では:s.pop()
  16.  
  17. アウト[4]: 1
  18.  
  19. [5]では
  20.  
  21. アウト[5]: []
  22.  
  23. # スタックが空かどうか確認する
  24.  
  25. [6]では: sではない
  26.  
  27. アウト[6]: 
  28.  
  29. [7]では: s.append(1)
  30.  
  31. [8]では: sではない
  32.  
  33. アウト[8]: 
  34.  
  35. # スタック内の要素数を取得する
  36.  
  37. [9] : len(s)
  38.  
  39. アウト[9]: 1
  40.  
  41. [10]では: s.append(2)
  42.  
  43. [11]では: s.append(3)
  44.  
  45. # スタックの一番上の要素を取得する
  46.  
  47. [12]では: s[-1]
  48.  
  49. アウト[12]: 3

多数の例

スタックの基本的な概念を理解した後、スタックを理解しやすくするためにいくつかの例を見てみましょう。

括弧のマッチング

トピック

式に 3 つの角括弧 ()、[]、{} を含めることができる場合、入れ子の順序は任意です。次に例を示します。

正しいフォーマット

  1. {()[()]},[{({})}]

形式が間違っています

  1. [()),[()),(()}

式文字列の括弧のマッチングが正しいかどうかを判断する関数を作成します。

アイデア

  1. まだ見つかっていない左括弧を格納するための空のスタックを作成します。
  2. 便利な文字列。左括弧に遭遇するとスタックにプッシュし、一致する右括弧に遭遇するとスタックに左括弧をポップします。
  3. 2 番目のステップでは、右括弧が空のスタックで見つかった場合、左括弧が欠落しており一致しないことを意味します。
  4. 2 番目のステップのトラバーサルの終了時にスタックが空でなく、右括弧が欠落していて一致しないことを示します。

ソリューションコード

理解を深めるためにpycharmでブレークポイントを設定することをお勧めします

  1. #!/use/bin/env python
  2.  
  3. # _*_ コーディング:utf-8 _*_
  4.  
  5. LEFT = { '(' , '[' , '{' } # 左括弧
  6.  
  7. RIGHT = { ')' , ']' , '}' } # 右括弧
  8.  
  9. def match(式):
  10.  
  11. 「」 「
  12.  
  13. :param expr: 渡された文字列
  14.  
  15. : return : 正しいかどうかを返します
  16.  
  17. 「」 「
  18.  
  19. stack = [] # スタックを作成する
  20.  
  21. for brackets in expr: # 渡されたすべての文字列を反復処理します
  22.  
  23. 括弧内の  LEFT : # 現在の文字が左括弧内にある場合
  24.  
  25. stack.append(brackets) # 現在の左括弧をスタックにプッシュします
  26.  
  27. elif括弧  RIGHT : # 右括弧の場合
  28.  
  29. スタックしない場合  1 <= ord(brackets) - ord(stack[-1]) <= 2ではない:
  30.  
  31. # 現在のスタックが空の場合、()]
  32.  
  33. # 右括弧の値から左括弧の値を引いた値が2以下でなく1以上である場合
  34.  
  35. 戻る  False # Falseを返します 
  36.  
  37. stack.pop() # 左括弧を削除
  38.  
  39. 戻る  not stack # スタックに値がない場合にはTrueを返し、そうでない場合はFalseを返します 
  40.  
  41. 結果 = 一致( '[(){()}]' )
  42.  
  43. 印刷(結果)

迷路問題

トピック

2 次元配列を使用して単純な迷路を表します。0 はパスを表し、1 は障害物を表します。各ポイントで、マウスは東、南、西、北の 4 つの隣接ポイントに移動できます。マウスが迷路を歩く様子をシミュレートし、入口から出口までのパスを見つけるアルゴリズムを設計します。

図に示すように

正しい出口ルートは写真の赤い線で示されています

アイデア

  1. スタックを使用して、入口から出口までのマウスの経路を記録します。
  2. 特定のポイントに到達したら、そのポイントの左側をスタックにプッシュし、そのポイントの値を 1 に設定して、通過したことを示します。
  3. 到達可能な近くの 4 つのポイントのいずれかを選択し、そのポイントまで歩きます。
  4. あるポイントに到達した後、隣接する 4 つのポイントに行かない場合は、行き止まりに達したことを意味します。このときは、スタックから撤退して 1 ステップ戻り、他のポイントを試す必要があります。
  5. 出口が見つかるまで手順 2、3、4 を繰り返します。

ソリューションコード

  1. #!/use/bin/env python
  2.  
  3. # _*_ コーディング:utf-8 _*_
  4.  
  5. initMaze() を定義します:
  6.  
  7. 「」 「
  8.  
  9. : return : 迷路を初期化する
  10.  
  11. 「」 「
  12.  
  13. maze = [[0] * 7 for _ in range(5 + 2)] # リストの内包表記を使用して、迷路が壁に囲まれていることを確認するために 7*7 の 2 次元配列を作成します
  14.  
  15. walls = [ # 壁の位置を記録する
  16.  
  17. (1、3)、
  18.  
  19. (2、1)、(2、5)、
  20.  
  21. (3、3)、(3、4)、
  22.  
  23. (4, 2), # (4, 3), # ポイント (4, 3) も壁として設定されている場合、迷路全体を歩くことはできないため、空のリストが返されます。
  24.  
  25. (5、4)
  26.  
  27. ]
  28.  
  29. for i in range(7): # 迷路の周りに壁を設定する
  30.  
  31. 迷路[i][0] = 迷路[i][-1] = 1
  32.  
  33. 迷路[0][i] = 迷路[-1][i] = 1
  34.  
  35. for i, j in walls: # すべての壁の点を 1 に設定する
  36.  
  37. 迷路[i][j] = 1
  38.  
  39. 迷路を戻る
  40.  
  41. 「」 「
  42.  
  43. [1、1、1、1、1、1、1]
  44.  
  45. [1, 0, 0, 1, 0, 0, 1]
  46.  
  47. [1、1、0、0、0、1、1]
  48.  
  49. [1、0、0、1、1、0、1]
  50.  
  51. [1, 0, 1, 0, 0, 0, 1]
  52.  
  53. [1, 0, 0, 0, 1, 0, 1]
  54.  
  55. [1、1、1、1、1、1、1]
  56.  
  57. 「」 「
  58.  
  59. 定義パス(迷路、開始、終了):
  60.  
  61. 「」 「
  62.  
  63. :param 迷路: 迷路
  64.  
  65. :param start: 開始点
  66.  
  67. :param end : 終了点
  68.  
  69. : return : ウォークの各ポイント
  70.  
  71. 「」 「
  72.  
  73. i, j = start # 開始点の座標の分解
  74.  
  75. ei, ej = end # 終点の左側への分解
  76.  
  77. stack = [(i, j)] # スタックを作成し、マウスを開始点に立たせます
  78.  
  79. maze[i][j] = 1 # 歩いた道は1に設定されます
  80.  
  81. while stack: # スタックが空でない場合は続行し、そうでない場合は終了する
  82.  
  83. i, j = stack[-1] # マウスの現在の位置を取得します
  84.  
  85. if (i, j) == (ei, ej): break # マウスが出口を見つけたら
  86.  
  87. di、dj[(0, -1), (0, 1), (-1, 0), (1, 0)]場合: # 左、右、上、下
  88.  
  89. if maze[i + di][j + dj] == 0: # 現在のポイントがアクセス可能かどうか
  90.  
  91. maze[i + di][j + dj] = 1 # 現在のポイントを1に設定する
  92.  
  93. stack.append((i + di, j + dj)) # 現在の位置をスタックに追加する
  94.  
  95. 壊す
  96.  
  97. else : # すべてのポイントにアクセスできない場合
  98.  
  99. stack.pop() # 1ステップ戻る
  100.  
  101. スタックを返す# 迷路を歩くことができない場合は、空のスタックを返す
  102.  
  103. Maze = initMaze() # 迷路を初期化する
  104.  
  105. result = path(maze=Maze, start=(1, 1), end =(5, 5)) # マウスは迷路の中を歩き始めます
  106.  
  107. 印刷(結果)
  108.  
  109. # [(1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (4, 1), (5, 1), (5, 2), (5, 3), (4, 3), (4, 4), (4, 5), (5, 5)]

後置式の評価

トピック

式を評価するとき、コンパイラは通常、括弧を必要としない接尾辞式を使用します。

接尾辞式評価関数を実装するプログラムを作成します。

アイデア

  1. 計算するオペランドを格納するスタックを作成します。
  2. 文字列をトラバースし、オペランドに遭遇したときにそれをスタックにプッシュし、演算記号に遭遇したときにオペランドをポップし(n回)、対応する計算を実行し、計算結果は新しいオペランドとしてスタックにプッシュされ、計算を待機します。
  3. 上記のプロセスに従って、式全体が走査され、最終結果のみがスタックに残ります。

ソリューションコード

  1. #!/use/bin/env python
  2.  
  3. # _*_ コーディング:utf-8 _*_
  4.  
  5. 演算子 = { # 演算子演算テーブル
  6.  
  7. '+' : ラムダ op1, op2: op1 + op2,
  8.  
  9. '-' : ラムダ op1, op2: op1 - op2,
  10.  
  11. '*' : ラムダ op1, op2: op1 * op2,
  12.  
  13. '/' : ラムダ op1, op2: op1 / op2,
  14.  
  15. }
  16.  
  17. def evalPostfix(e):
  18.  
  19. 「」 「
  20.  
  21. :param e: 接尾辞式
  22.  
  23. : return : 通常、スタックの最初の要素は計算された値です。
  24.  
  25. 「」 「
  26.  
  27. tokens = e.split() # 渡されたサフィックス式をリストに分割します
  28.  
  29. スタック = []
  30.  
  31. for token in tokens: # リスト内の要素を反復処理する
  32.  
  33. if token.isdigit(): # 現在の要素が数値の場合
  34.  
  35. stack.append( int (token)) # スタックに追加する
  36.  
  37. elifトークンin operators.keys(): # 現在の要素が演算子の場合
  38.  
  39. f = operators[token] # 演算子操作テーブル内の対応するラムダ式を取得します
  40.  
  41. op2 = stack.pop() # 先入後出原則に従って、2番目の要素を最初にスタックからポップします
  42.  
  43. op1 = stack.pop() # スタックから最初の要素を取り出す
  44.  
  45. stack.append(f(op1, op2)) # 計算結果をスタックに格納する
  46.  
  47. return stack.pop() # スタックの最初の要素を返します
  48.  
  49. 結果 = evalPostfix( '2 3 4 * +' )
  50.  
  51. 印刷(結果)
  52.  
  53. #14

ナップサック問題

トピック

10kgの荷物を収納できるバックパックがあります。現在、6つのアイテムがあります。

アイテム 1 + アイテム 5 など、バックパックを満たすことができるすべてのソリューションを検索するプログラムを作成します。

ソリューションコード

  1. #!/use/bin/env python
  2.  
  3. # _*_ コーディング:utf-8 _*_
  4.  
  5. ナップサック(t, w)を定義します:
  6.  
  7. 「」 「
  8.  
  9. :param t: バックパックの総容量
  10.  
  11. :param w: アイテムの重量リスト
  12.  
  13. 戻る
  14.  
  15. 「」 「
  16.  
  17. n = len(w) # 選択できる項目の数
  18.  
  19. stack = [] # スタックを作成する
  20.  
  21. k = 0 # 現在選択されている項目のカーソル
  22.  
  23. while スタックまたはk < n: # スタックが空ではない、または k < n
  24.  
  25. while t > 0 and k < n: # まだスペースが残っているので、アイテムを入れることができます
  26.  
  27. if t >= w[k]: # 残りのスペースが現在のアイテムの重量以上である
  28.  
  29. stack.append(k) # アイテムをバックパックに装備する
  30.  
  31. t -= w[k] # バックパックのスペース削減
  32.  
  33. k += 1 # 後方検索を続ける
  34.  
  35. if t == 0: # 解を求める
  36.  
  37. 印刷(スタック)
  38.  
  39. # フォールバックプロセス
  40.  
  41. k = stack.pop() # 最後の項目を取り出す
  42.  
  43. t += w[k] # バックパックの総容量にw[k]を加えた値
  44.  
  45. k += 1 # 次の項目をロードする
  46.  
  47. ナップザック(10, [1, 8, 4, 3, 5, 2])
  48.  
  49. 「」 「
  50.  
  51. [0、2、3、5]
  52.  
  53. [0, 2, 4]
  54.  
  55. [1, 5]
  56.  
  57. [3, 4, 5]
  58.  
  59. 「」 「

<<:  「ディープラーニング」市場の動向を多面的に分析

>>:  データマイニングのコアアルゴリズムの一つである回帰

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

インテル、コード名「NLP Architect」の自然言語処理用オープンソースライブラリを発表

[[230933]] 1年前に設立されたインテルAIラボは最近、新たな動きを見せている。数日前、In...

...

Facebook、MITなどが研究論文を発表:ディープラーニングの実際の仕組みを説明する理論

Facebook、プリンストン大学、MITのAI研究者らは最近、「ディープラーニング理論の原理:ニュ...

GPT-4/Llama2のパフォーマンスを大幅に向上させるためにRLHFは必要ない、北京大学のチームはAlignerの新しいアライメントパラダイムを提案

背景大規模言語モデル (LLM) は強力な機能を発揮していますが、不快な応答、虚偽の情報、漏洩した個...

ビッグニュース!アリママが自社開発のCTR推定コアアルゴリズムMLRを初公開

1. 技術的背景CTR(Click-Through-Rate)とは、クリック率のことで、インターネッ...

...

RL エージェントはオンラインでしかトレーニングできないと誰が言ったのでしょうか? Google がオフライン強化学習の新しいパラダイムを発表

分布の不一致を避けるために、強化学習のトレーニングはオンラインで環境と対話する必要がありますか? G...

...

Xing Bo 氏のチームの LLM360 は、大規模なモデルを真に透明化する総合的なオープンソース プロジェクトです。

オープンソース モデルは、数だけでなくパフォーマンスも増加しており、活発な活力を示しています。チュー...

AI とデジタル病理学は医療通信をどのように改善できるのでしょうか?

人工知能 (AI) とデジタル病理学は、特に通信分野において医療業界に革命をもたらすと期待されていま...

Java プログラミング スキル - データ構造とアルゴリズム「非再帰的バイナリ検索」

[[396063]]基本的な紹介1. バイナリ検索は、順序付けられたシリーズ(数字や文字など)の検...

...

自動運転・ホログラム投影!映画に出てくるブラックテクノロジーは私たちからどれくらい遠いのでしょうか?

春節休暇期間中、国内映画市場は活況を呈した。猫眼専門版のデータによると、丑年春節期間(2月11日~2...

自然言語処理の実践: 機械学習によく使われるツールとテクニック

多くの自然言語処理には機械学習が関係しているため、機械学習の基本的なツールとテクニックを理解しておく...