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. 「」 「

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

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

ブログ    
ブログ    

推薦する

2020 年に爆発的に増加する 9 つの AI マーケティング トレンド

マーケティングに AI を使用すると、代理店の専門家の作業がさまざまな点で楽になります。消費者に合わ...

セキュリティ業界の大手企業はどのようにドローンを配備するのでしょうか?

ドローンは警報装置、検出器、カメラなどを搭載し、多くの機能を実現でき、セキュリティ監視、スマートビル...

...

...

機械学習モデルのトレーニングの全プロセス!

週末に家で退屈していたので、GitHub を閲覧していたところ、非常に興味深いオープンソース プロジ...

人工知能はデジタルマーケティング革命において否定できないトレンドとなっている

人工知能 (AI) は、現在、デジタル マーケティング革命における否定できないトレンドとなっています...

Panda-Gym のロボットアームシミュレーションを使用したディープ Q 学習強化学習

強化学習 (RL) は、エージェントが試行錯誤を通じて環境内でどのように動作するかを学習できるように...

サイバーセキュリティにおける人工知能の長所と短所

今日では、かつてないほど多くのデータが生成されています。データ分析ツールの発達により、あらゆる分野の...

機械学習とディープラーニング、この2つの違いは何でしょうか?

[51CTO.com クイック翻訳] 機械学習とディープラーニング - 両者の類似点と相違点。人工...

自律飛行ロボットが浙江大学から集団で飛び立ち、サイエンス誌の表紙に登場

最近、浙江省安吉市の竹林で、一群の超小型知能ドローンが集団で派遣され、ジャングルの中を楽々と移動した...

わずか数分で 8 文字のパスワードを解読するにはどうすればよいでしょうか?

翻訳者 |ブガッティレビュー | Chonglouセキュリティの専門家は長い間、オンラインアカウント...

テキスト生成画像は非常に人気があり、これらの技術の進化を理解する必要があります

OpenAIは最近、AIコミュニティに「地震」を引き起こしたDALL・E 2システムをリリースしま...

私の国の自動運転開発は、年初に巨額の資金提供を受けて大いに支持されている

自動運転は、さまざまな交通問題を解決し、スマートシティの発展を実現するための共通の選択肢として、近年...

ハッカーがAIとMLを駆使して企業を狙う方法

サイバーセキュリティは AI と ML の進歩の恩恵を受けています。今日のセキュリティ チームは、疑...