質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2953閲覧

DFS(深さ優先探索)の行きがけ順と帰りがけ順の順序を示すコードをc++からPythonにうまく翻訳できません

trader65

総合スコア18

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

1クリップ

投稿2020/05/13 04:07

編集2020/05/13 04:08

前提・実現したいこと

この記事で紹介されている,グラフをDFSで走査し,行きがけ順と帰りがけ順の順序を出力するc++のコードをPythonに翻訳しようとしています.

理想

記事では,次のようなコードで,

cpp

1#include <iostream> 2#include <vector> 3using namespace std; 4using Graph = vector<vector<int>>; 5 6vector<bool> seen; 7vector<int> first_order; // 行きがけ順 8vector<int> last_order; // 帰りがけ順 9 10void dfs(const Graph &G, int v, int& first_ptr, int& last_ptr) { 11 // 行きがけ順をインクリメントしながらメモ 12 first_order[v] = first_ptr++; 13 14 seen[v] = true; 15 for (auto next_v : G[v]) { 16 if (seen[next_v]) continue; 17 dfs(G, next_v, first_ptr, last_ptr); 18 } 19 20 // 帰りがけ順をインクリメントしながらメモ 21 last_order[v] = last_ptr++; 22} 23 24int main() { 25 // 頂点数と辺数 26 int N, M; cin >> N >> M; 27 28 // グラフ入力受取 (ここでは無向グラフを想定) 29 Graph G(N); 30 for (int i = 0; i < M; ++i) { 31 int a, b; 32 cin >> a >> b; 33 G[a].push_back(b); 34 G[b].push_back(a); 35 } 36 37 // 頂点 0 をスタートとした探索 38 seen.assign(N, false); // 全頂点を「未訪問」に初期化 39 first_order.resize(N); 40 last_order.resize(N); 41 int first_ptr = 0, last_ptr = 0; 42 dfs(G, 0, first_ptr, last_ptr); 43 44 // 各頂点 v の行きがけ順、帰りがけ順を出力 45 for (int v = 0; v < N; ++v) 46 cout << v << ": " << first_order[v] << ", " << last_order[v] << endl; 47}

次のような出力が返るようになっています.

c++

10: 0, 14 21: 1, 2 32: 2, 0 43: 3, 1 54: 4, 9 65: 5, 5 76: 6, 3 87: 7, 4 98: 8, 8 109: 9, 6 1110: 10, 7 1211: 11, 13 1312: 12, 10 1413: 13, 12 1514: 14, 11

これをそのままPythonに翻訳することが理想です.

発生している問題

翻訳するつもりで,次のように書きました.

Python

1 2N, M = map(int, input().split()) # 頂点数,辺数 3G = [[] for _ in range(N)] 4 5for i in range(M): 6 a, b = map(int, input().split()) 7 G[a].append(b) 8 G[b].append(a) 9 10seen = [False]*N 11first_order = [0]*N 12last_order = [0]*N 13first_ptr = 0 14last_ptr = 0 15 16 17def dfs(G, v, first_ptr, last_ptr): 18 19 first_ptr += 1 20 first_order[v] = first_ptr 21 22 seen[v] = True 23 24 for next_v in G[v]: 25 if seen[next_v]: 26 continue 27 dfs(G, next_v, first_ptr, last_ptr) 28 29 last_ptr += 1 30 last_order[v] = last_ptr 31 32 33dfs(G, 0, first_ptr, last_ptr) 34 35for v in range(N): 36 print('{}: {}, {}'.format(v, first_order[v], last_order[v])) 37

しかしその結果返ってくる出力は次のもので,想定と異なっています.

python

10: 1, 1 21: 2, 1 32: 3, 1 43: 3, 1 54: 2, 1 65: 3, 1 76: 4, 1 87: 4, 1 98: 3, 1 109: 4, 1 1110: 4, 1 1211: 2, 1 1312: 3, 1 1413: 3, 1 1514: 4, 1

どのように変更すれば想定通りの出力が得られるのでしょうか?

インクリメントがうまくいっていないことは明らかなのですが,なぜそうなのかの見当がつきませんでした.初歩的な質問で恐縮ですが,ご検討いただけると大変助かります.

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

おそらくここですね

Python def dfs(G, v, first_ptr, last_ptr): C++ void dfs(const Graph &G, int v, int& first_ptr, int& last_ptr) { // A void dfs(const Graph &G, int v, int first_ptr, int last_ptr) { // B

Aがオリジナル、BがPythonのコードの解釈になります。
どう違うのかはC++の本を読み直して下さい。

Pythonでは、C++のint &という書式はありません
代わりとしてはこんな感じでしょうか

outlist = [0, 0] def dfs(G, v, outlist): //first_ptr += 1 outlist[0] += 1

投稿2020/05/13 04:51

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

trader65

2020/05/13 05:38

ご回答ありがとうございます.参照渡しであるべきところが値渡しになってしまっていたのですね.大変勉強になりました!
guest

0

ベストアンサー

動かすだけであれば、以下のように書き換えてfirst_ptr, last_ptrをポインタ経由でアクセスしているっぽくするのが簡単かと思います。
なお、元のC++プログラムでは後置インクリメントなので代入した後に値をインクリメントしています。
pythonプログラムもそれに合わせて代入とインクリメントの順番を変える必要があります。

python

1N, M = map(int, input().split()) # 頂点数,辺数 2G = [[] for _ in range(N)] 3 4for i in range(M): 5 a, b = map(int, input().split()) 6 G[a].append(b) 7 G[b].append(a) 8 9seen = [False]*N 10first_order = [0]*N 11last_order = [0]*N 12first_ptr = [0] 13last_ptr = [0] 14 15 16def dfs(G, v, first_ptr, last_ptr): 17 first_order[v] = first_ptr[0] 18 first_ptr[0] += 1 19 seen[v] = True 20 21 for next_v in G[v]: 22 if seen[next_v]: 23 continue 24 dfs(G, next_v, first_ptr, last_ptr) 25 26 last_order[v] = last_ptr[0] 27 last_ptr[0] += 1 28 29 30dfs(G, 0, first_ptr, last_ptr) 31 32for v in range(N): 33 print('{}: {}, {}'.format(v, first_order[v], last_order[v]))

投稿2020/05/13 04:46

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

trader65

2020/05/13 05:29

ご丁寧にありがとうございます! インクリの前置/後置の違いを恥ずかしながら意識したことがなく,大変勉強になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問