コンテンツにスキップ

第1回:アルゴリズムとデータ構造の概要

プログラムとは何か

プログラム = コンピュータになんらかの処理を行わせるための再現できる手順を書いた命令書

43 x 21 の筆算を例に考える。答えは903だが、「どうやって求めたか」が重要である。

  1. 43 x 1 を計算する
  2. 43 x 2 を計算する(十の位なので桁をずらす)
  3. 結果を足し合わせる → 903

この手順そのものが「プログラム」の一種である。

「筆算」のPythonプログラム

結果は同じ903でも、「電卓的な計算」と「人間の筆算」はやり方がまったく異なる。

電卓的な計算(x)

answer = 43 * 21
print(answer)  # 出力: 903

これはPythonの * 演算子に任せているだけで、「筆算」ではない。

筆算のプログラム(o)

def hissan_mul(a, b):
    a1, a0 = a // 10, a % 10
    b1, b0 = b // 10, b % 10

    print(f"  {a:>4}")
    print(f"x{b:>4}")
    print("-" * 6)

    carry = 0
    t = a0 * b0 + carry
    carry, r0 = t // 10, t % 10
    t = a1 * b0 + carry
    carry, r1 = t // 10, t % 10
    print(f"  {carry*100 + r1*10 + r0:>4}")

    carry = 0
    t = a0 * b1 + carry
    carry, r0 = t // 10, t % 10
    t = a1 * b1 + carry
    carry, r1 = t // 10, t % 10
    print(f" {carry*100 + r1*10 + r0:>4}")

    print("-" * 6)
    print(f"  {a * b:>4}")


hissan_mul(43, 21)

2つのポイント

  1. 人間がやっていることは意外と複雑である --- 筆算の手順をプログラムとして書き下すと、桁の分解・繰り上がりの処理など多くのステップが必要になる。
  2. コンピュータにはコンピュータの得意なやり方がある --- 43 * 21 と書けば一瞬で答えが出るが、それは人間の筆算とは全く異なるやり方である。

プログラミングの3ステップ

プログラミングは以下の3つのステップで構成される。

flowchart LR
    A[要求\n問題文] -->|ステップ1-2\nアルゴリズム\n思考| B[抽象的な処理\nフローチャート]
    B -->|ステップ2-3\nコーディング\n実装| C[具体的な処理\nPython/Cのコード]
  • ステップ1→2(アルゴリズム): 要求を理解し、説明できるレベルまで整理する
  • ステップ2→3(コーディング): 整理した手順をプログラミング言語に翻訳する

アルゴリズムの3つの基本構造

すべてのアルゴリズムは、以下の3つの構造の組み合わせで表現できる。

順次:上から順に実行

flowchart TD
    A[処理1] --> B[処理2] --> C[処理3]

分岐:条件によって処理を変える(if)

flowchart TD
    A{条件} -->|True| B[処理A]
    A -->|False| C[処理B]

反復:同じ処理を繰り返す(for / while)

flowchart TD
    A{条件} -->|True| B[処理]
    B --> A
    A -->|False| C[次の処理]

Pythonでの対応

  • 順次:文を上から順番に書く
  • 分岐:if / else
  • 反復:for / while

アルゴリズムの例:合格判定

要求: 学生全員の点数を見て、合格か不合格かを判定する。

フローチャート

flowchart TD
    A([開始]) --> B[点数リストを用意]
    B --> C[リストから点数を1つ取り出す]
    C --> D{60点以上?}
    D -->|Yes| E[合格]
    D -->|No| F[不合格]
    E --> G{次はある?}
    F --> G
    G -->|Yes| C
    G -->|No| H([終了])

Pythonコード

students = [75, 42, 88, 55, 90]
for student in students:
    if student >= 60:
        print("合格")
    else:
        print("不合格")

実行結果:

合格
不合格
合格
不合格
合格

フローチャートとコードの対応

  • 反復(「次はある?」→「リストから点数を1つ取り出す」に戻るループ)→ for student in students
  • 条件分岐(「60点以上?」)→ if student >= 60 / else
  • 順次(「合格」「不合格」の出力)→ print() が上から順に実行される

なぜPythonで学ぶのか

  • 読みやすく記法がシンプル: 初学者でも理解しやすい
  • 汎用性が高い: Web開発、データ分析、AIなど幅広い分野で使われる
  • 初学者に人気: 世界的にプログラミング教育で広く採用されている

Python vs C言語の比較

# Python
a = 1
b = 3
print(a + b)
// C言語
int a = 1;
int b = 3;
printf("%d", (a+b));

Pythonは型宣言が不要で、セミコロンも不要であり、記述量が少ない。

処理の拡張とデータ構造

もし学生が10万人いたら? 名前も知りたかったら? 学科ごとに判定したかったら?

リストだけでは厳しくなる。辞書? クラス? ファイル? データベース?

データ構造の選び方が重要になる。

データ構造とは

データ構造 = データの格納方法と、データの操作方法

同じデータでも「どう持つか」で速さもメモリも変わる。

格納方法の比較

データ構造(a):フラットテーブル

注文番号 住所 氏名
001 東京都... 山田太郎
002 東京都... 山田太郎
003 大阪府... 田中花子

同じ宛先の注文が複数あると、住所と氏名が重複して格納される。

データ構造(b):正規化テーブル

注文テーブル

注文番号 宛先記号
001 A
002 A
003 B

宛先テーブル

宛先記号 住所 氏名
A 東京都... 山田太郎
B 大阪府... 田中花子

格納の比較

  • (a) は同じ宛先の注文があると住所・氏名が重複し、メモリ領域が無駄になる
  • (b) は宛先記号に領域を使うが、重複がないため少ない領域で済む

操作の比較

  • (a) は注文番号から住所をすぐ表示できる(1つの表を見るだけ)
  • (b) は二つの表の宛先記号を照らし合わせる必要があり、時間がかかる

データ構造の選び方

  • (a) は検索が速いがメモリを食う
  • (b) はメモリ節約だが検索に手間がかかる

「どちらが良い」ではなく「何を優先するか」で選ぶ。これが速さ vs メモリのトレードオフである。

演習

演習課題1-1

目玉焼きの作り方について、わかりやすい説明を書いてみてください。

演習課題1-2

自転車を運転する方法について、わかりやすい説明を書いてみてください。

演習課題1-3

合否判定フローチャートを改造して「80点以上はA、60点以上はB、それ以外はC」と出力するプログラムを作成せよ。

追加課題

任意の点数基準に対応するにはどうすればよいか考えてみよう。