フローチャート入門

フローチャートとは

フローチャート(flowchart)とは、プログラムの流れを図解する手段で、別名「流れ図」ともよばれています。

フローチャートを書く3つの目的

  1. プログラム構造の整理

    1つ目の目的はプログラム構造を整理することです。プログラムが正しいか、他の人にレビュー(確認)してもらうこともできるようになります。

  2. 効率的にプログラムを作るため

    2つ目の目的は効率的にプログラムを作るためです。正しいプログラム構造ができていれば、効率的にプログラムを書くことが出来、後々何回も修正するような無駄を省くことができます。

  3. プログラム品質の向上

    フローチャートを書くことでプログラムの全体像が明確になり、漏れやバグを減らすことができ、品質が上がります。

フローチャートを効率よく学び、作る方法

  • ステップ1

    まず記号をおぼえる。数は多くありません。

  • ステップ2

    基本の型や事例をまねしながら、フローチャートを書いてみる。

    フローチャートは、googleドキュメントから「描画」を挿入し、新規の図形描画の中で図形を選択すると下の方にいろいろなフローチャートの記号が選択できるので、これを使って簡単に書くことができます。

    また、visual studio codeをインストールし、拡張機能でDraw.io Integrationをインストールすることでフローチャートを作成することもできます。

フローチャートの基本ルール(記号)

フローチャートは決められた記号を組み合わせて書きます。使う記号を間違えると意味が変わってしまうため、しっかり記号をおぼえてください。記号はそれほど多くありません。

開始/終了

flowchart TD A(開始)

フローチャートの開始と終了を表示する記号です。「端子」とも呼ばれています。記号の中に「開始」や「終了」と書いて使います。

処理

flowchart TD A[処理内容]

処理内容を表示する際に使う記号です。処理記号の中に処理内容を書いて使います。

条件分岐

flowchart TD A{条件}

条件分岐を表示する際に使う記号です。記号の中に条件を書いて使います。

定義済み処理

flowchart TD A[[定義済み
処理内容]]

別ページのフローチャートで定義されている一連の処理などを表現する時に使う記号です。別名「サブルーチン(関数)」とも呼ばれています。記号の中に定義済み処理名(関数名)を書いて使います。

入出力

flowchart TD A[/入出力
内容/]

外部データの参照や外部データの書込み、ファイルの入出力などを表現する際に使う記号です。入出力記号の中に、内容を書いて使います。

結合子

flowchart TD A((数字または
参照先名))

別の処理に飛ばす際に使う記号です。「◯◯参照」を意味します。フローチャートが長くなったり、複雑化した際などに使います。結合子の中に参照先を明示して使います。

フローチャートの基本の型(まねその1)

フローチャートには、よく使われる「基本の型」があります。

フローチャートを簡単に作成するには、この「型」をおぼえるのが第一歩です。

すぐおぼえられなくても、まねしているうちにいつの間にかおぼえてしまうものです。

順次構造

順次構造とは、処理する順番に記述されているプログラム構造のことです。

単純に、上から下に処理が流れていくシンプルな構造をしています。

前述したフローチャートの記号を並べて矢印でつなぐだけでOKです。

順次構造の例

%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始) --> B[[処理A]] --> C[[処理B]] --> D[/ログ出力/] --> E(終了)

分岐構造

分岐構造とは、条件によって処理内容が分かれるプログラム構造のことです。

分岐条件は、ひし形の記号を使って表現します。

例えば、Pythonのif elseなどを表現する際に使います。

if・else文を表現する場合は、下図のように条件分岐と処理の記号を組み合わせるだけで書くことができます。どの条件にも一致しなかったときの処理(下図では処理4)を忘れないようにしてください。

if・else文の例

%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD H(開始) --> A{条件1} -- Yes--> B[処理1] --> I(終了) A -- No --> C{条件2} C -- Yes --> D[処理2] --> I C -- No --> E{条件3} E -- Yes --> F[処理3] --> I E -- No --> G[処理4] --> I

反復構造(ループ)

反復構造とは、条件を満たしている間、または条件を満たすまで処理を繰り返すプログラム構造のことです。たとえばPythonではfor文やwhile文などを表現する際に使います。下図のように「条件分岐記号」を使用して表現します。

反復構造の例

%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始) --> B[i = 1] --> C{i <= 10} -- Yes --> D["print(i)"]--> E[i += 1] --> C C -- No ---> F(終了)

ループ構造の中にさらにループ構造がある構造のことを「二重ループ」と言います。

九九の表を処理するときのように2つの軸(2次元といいます)のデータを処理するときなどに使われます。

二重ループの例

%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始) --> B[処理1] --> C{条件} -- Yes --> D{条件} -- Yes --> E[処理2] --> D C -- No ----> F(終了) D -- No ---> G[処理3] --> C

アルゴリズムをフローチャートで書いてみる

ある課題に対してそれを解決するための処理手順のことを「アルゴリズム」といいます。アルゴリズムをフローチャートで図解してみましょう。

例として「バブルソート」のアルゴリズムをフローチャート化してみます。

バブルソート

ばらばらの数字の配列(数字が並んだ列)を値の小さい順(または大きい順)に並び替えることを「ソート(Sort)」といいます。小さい順に並べるのを「昇順ソート」、大きい順に並べるのを「降順ソート」といいます。今回は「昇順ソート」を行います。

「ソート」のアルゴリズムにはいろいろありますが、比較的単純な方法(アルゴリズム)に「バブルソート」と呼ばれるアルゴリズムがあります。

アルゴリズム

配列の全ての要素に対して、隣接する要素を比較し、順番が逆であれば入れ替えるという操作を配列の先頭から最後尾まで行えば、一番大きい値が最後尾にくるので最後尾の値が確定します。次に、この処理を配列の先頭から値が確定した最後尾の1つまで行います。全ての値が確定するまでこの処理を繰り返すと、配列が昇順にソートされます。

ソートする数字の配列をa、配列の長さをnとします。配列の各要素は、a[0], a[1], a[2], ..., a[n-1]と表現することができます。

確定した要素の位置をkとします。kの初期値は全ての値が確定していないので最後尾+1すなわちnになります。kの値が先頭すなわち0になれば全ての値が確定し、ソートが終了したことになります。

フローチャート

%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始) --> B[k = n] --> C{k > 0} -- Yes --> D[i = 0] --> E{i < k-1} --Yes --> F{"a[i] > a[i+1]"} -- Yes --> G["a[i]とa[i+1]を交換"] --> H[i = i + 1] --> E F -- No --> H E -- No --> I[k = k - 1] --> C C -- No ------> J(終了)

フローチャートからプログラムを書く

前述のバブルソートのフローチャートからPythonのプログラムを書いてみましょう。

まず、配列aに初期データとして8 4 3 7 6 5 2 1というソートされていない値を設定します。配列の長さn8です。

a = [8, 4, 3, 7, 6, 5, 2, 1]
n = 8

「開始」「終了」は今回は必要ないので無視します。(関数なら開始が関数定義(def)、終了がreturnになります)

最初のステップで変数knを設定します。

k = n

次のステップでk0より大きいか比較し、大きければループ処理に入り、そうでなければループ処理を終了します。

while k > 0:
    ...

最初のループ処理では、i0で初期化し、さらに次のステップでik-1より小さい間、2番目のループ処理に入り、そうでなければ2番目のループ処理を終了します。2番目のループ処理が終わったら、iに1を加えます。pythonではこの3つのステップをまとめてfor文で処理します。

    for i in range(k-1);
        ...

range(k-1)range(0, k-1, 1)と同じ意味で、変数i0で初期化し、変数ik-1より小さい間以下のループ処理を行い、ループ処理終了後変数i1を加算することを示しています。

2番目の処理ループでは、a[i]a[i+1]を比較し、a[i]の方が大きければ、a[i]a[i+1]の値を交換します。pythonでは値の交換はa[i], a[i+1] = a[i+1], a[i]と表現することができます。

        if a[i] > a[i+1]:
            a[i], a[i+1] = a[i+1], a[i]

2番目のループを終了したら、変数kの値を1つ減らして、最初のループに戻ります。

    k -= 1

以上でフローチャートからPythonのプログラムの作成は終了です。

Pythonのプログラムを整理すると以下のようになります。

a = [8, 4, 3, 7, 6, 5, 2, 1]
n = 8
k = n
while k > 0:
	for i in range(k-1):
		if a[i] > a[i+1]:
			a[i], a[i+1] = a[i+1], a[i]
	k -= 1

最後にprint(a)を実行して配列aがソートされて[1, 2, 3, 4, 5, 6, 7, 8]になっていることを確認してください。

演習問題

演習問題1 選択ソート(selection sort)

選択ソート(selection sort)とは、ソートアルゴリズムの1つで、配列から最小値を探し、配列の先頭要素と入れ替えることを繰り返して並べ替えを行うものである。

アルゴリズム

選択ソートは以下の手順で行います。

  1. 1番目の要素から最後尾の要素までで最も値の小さいものを探し、それを1番目の要素と交換する(1番目の要素までソート済みとなる)

  2. 2番目の要素から最後尾の要素までで最も値の小さいものを探し、それを2番目の要素と交換する(2番目の要素までソート済みとなる)

  3. 以降同様に、未ソート部分の最小要素を探索し、未ソート部分の先頭要素と交換する

  4. 全ての要素がソート済みになったら処理を終了する

問題

  1. 選択ソートのアルゴリズムのフローチャートを作成してください

  2. 作成したフローチャートからPythonでプログラムを作成し、バブルソートのときと同じテストデータを使って正しくソートされるか確認してください

ヒント

  • ソート済みの要素数を変数kとし、初期値を0とします。最小値を探す処理が終了するたびにkの値が1つずつ増え、値が配列aの長さnになったらソート終了です。

  • 最小値を探す対象はa[k]の要素からa[n-1]の要素までです。

  • 最小値とその位置を探す方法は、まず探す対象の先頭の位置を変数miniに入れます。先頭の位置はkなのでmini = kとなります。

  • 次に先頭から次の値a[k+1]から最後尾a[n-1]まで現在の最小値a[mini]と比較し、値が変数a[mini]より小さい場合は変数miniを小さい方の位置に書き換えます。

  • 最後尾に達したらa[mini]の値が最小値なので、この値と先頭の値a[k]を交換します。a[k], a[mini] = a[mini], a[k]

回答例
%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始) --> B[k = 0] --> C{k < n} -- Yes --> D[mini = k] --> E[i = k+1] --> F{i < n} -- Yes --> G{"a[i] < a[mini]"} -- Yes --> H[mini = i] --> I[i += 1] --> F G -- No --> I F -- No ---> J["a[k]とa[mini]を交換"] --> K[k += 1] --> C C -- No -------> L(終了)
a = [8, 4, 3, 7, 6, 5, 2, 1]
n = 8
k = 0
while k < n:
    mini = k
    for i in range(k+1, n):
        if a[i] < a[mini]:
            mini = i
    a[k], a[mini] = a[mini], a[k]
    k += 1

演習問題2 挿入ソート(insertion sort)

挿入ソート(insertion sort)とは、ソートアルゴリズムの1つで、配列の整列済みの部分に追加要素を適切な場所に挿入することを繰り返すことで並べ替えを行う方法である。

アルゴリズム

挿入ソートは以下の手順で行います。

  1. 0番目と1番目の要素を比較し、0番目の方が大きければ入れ換える。この操作で1番目までのデータが整理済みとなる。

  2. 2番目の要素が1番目までの要素より小さければ、正しい順番に並べるように2番目の要素を挿入する。(2番目の要素を変数に保存し、2番目より要素が大きい間、その要素を1つずつずらし、適切な位置に保存した変数の値を書き込む)。この操作で2番目までのデータが整理済みとなる。

  3. このあと、3番目以降の要素について整理済みデータとの比較と適切な位置への挿入を繰り返す。

問題

  1. 挿入ソートのアルゴリズムのフローチャートを作成してください

  2. 作成したフローチャートからPythonでプログラムを作成し、バブルソートのときと同じテストデータを使って正しくソートされるか確認してください

ヒント

  • 整理済みの要素数を変数kとし、0で初期化します。挿入による再整理が終了するたびに変数kを1つ加算し、この値が変数の長さn-1になったら全ての要素が整理済みとなるのでソートを終了します。

  • まず変数tmpa[k+1]の値を保存します。

  • 変数ik+1に初期化します。

  • 変数i0より大きいかつa[i-1]tmpよりおおきければa[i-1]の値をa[i]に書き込み(要素を1つずらす)、変数iを1つ減らします。

  • a[i]に変数tmpの値を書き込みます

回答例
%%{init:{'themeVariables':{'lineColor':'#FFFFFFFF'}}}%% flowchart TD A(開始)-->B[k = 0]-->C{k < n-1}-- Yes -->D["tmp = a[k+1]"] -->E[i = k+1]-->F{"i > 0 and a[i-1] > tmp"}-- Yes -->G["a[i] = a[i-1]"] -->H[i -= 1]-->F F-- No --> I["a[i] = tmp"]--> J[k += 1]-->C
a = [8, 4, 3, 7, 6, 5, 2, 1]
n = 8
k = 0
while k < n - 1:
    tmp = a[k+1]
    i = k+1
    while i > 0 and a[i-1] > tmp:
        a[i] = a[i-1]
        i -= 1
    a[i] = tmp
    k += 1