C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で与えられた行列を対角行列に変換するプログラムの作成方法

n×n のサイズで与えられた行列を、種類を問わず対角行列へ変換するのが本記事のテーマです。C++による実装方法を、考え方・アルゴリズム・サンプルコード・実行結果まで含めてわかりやすく解説します。

対角行列とは?

対角行列とは、n×n の正方行列のうち、対角成分(行番号と列番号が一致する要素)以外のすべての要素が 0 である行列を指します。対角成分自体には任意の値を入れることができます。

下図は、非対角成分を 0 に変換するイメージです。

| 1  2  3 |          | 1  0  3 |
| 4  5  6 |    →     | 0  5  0 |
| 7  8  9 |          | 7  0  9 |

変換のアプローチ

変換の手順は非常にシンプルです。行列内の全要素を二重ループで走査し、i と j が一致しない要素(非対角成分)を見つけたら 0 に置き換えます。対角成分(i == j の要素)は元の値のまま変更しません。

入力例と出力例

例 1

入力:matrix[3][3] = {{ 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 }}
出力:{{ 1, 0, 3 },
      { 0, 5, 0 },
      { 7, 0, 9 }}

例 2

入力:matrix[3][3] = {{ 91, 32, 23 },
                    { 40, 51, 26 },
                    { 72, 81, 93 }}
出力:{{ 91, 0, 23 },
      { 0, 51, 0 },
      { 72, 0, 93 }}

アルゴリズム

開始
ステップ 1 → 行列のサイズを定数として定義する(const int n = 10)
ステップ 2 → 対角行列へ変換する関数を用意する
    void diagonal(int arr[][n], int a, int m)
        ループ(int i = 0; i < a; i++)
            ループ(int j = 0; j < m; j++)
                もし i != j なら
                    arr[i][j] に 0 を代入
                条件終了
            ループ終了
        ループ終了
        ループ(int i = 0; i < a; i++)
            ループ(int j = 0; j < m; j++)
                arr[i][j] を出力
            ループ終了
            改行を出力
        ループ終了
ステップ 3 → main() 内の処理
    行列を宣言する:int arr[][n] = {{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}
    関数を呼び出す:diagonal(arr, 3, 3)
終了

C++ サンプルコード

#include <iostream>
using namespace std;

const int n = 10;

// n×n 行列の非対角成分を 0 に置き換える関数
void diagonal(int arr[][n], int a, int m) {
    // 非対角成分を 0 にする
    for (int i = 0; i < a; i++) {
        for (int j = 0; j < m; j++) {
            if (i != j)
                arr[i][j] = 0;
        }
    }
    // 変換後の行列を表示する
    for (int i = 0; i < a; i++) {
        for (int j = 0; j < m; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}

int main() {
    int arr[][n] = { { 1, 2, 3 },
                     { 4, 5, 6 },
                     { 7, 8, 9 } };
    diagonal(arr, 3, 3);
    return 0;
}

実行結果

上記のコードをコンパイルして実行すると、次の出力が得られます。

1 0 3
0 5 0
7 0 9

コードのポイント

  • 条件「i != j」 … 行と列の番号が異なる要素=非対角成分なので、0 に置き換えています。
  • 時間計算量 O(n²) … 行列の全要素を 1 回ずつ走査するためです。
  • 空間計算量 O(1) … 元の配列を直接書き換えるため、追加のメモリが不要です。

なお、主対角線に加えて反対角線(右上がりの対角線)も残したい場合は、条件を「i != j && i + j != a - 1」に変更すれば対応できます。このように、二重ループとひとつの条件分岐だけで、任意の正方行列を簡単に対角行列へ変換することが可能です。

  1. C++で対角行列・スカラー行列を判定するプログラムの書き方

    行列 M[r][c] が与えられたとき、「r」は行数、「c」は列数を表し、r = c のとき正方行列となります。本記事では、与えられた正方行列が対角行列であるか、スカラー行列であるかを判定し、該当する場合には「yes」を出力する方法を解説します。 対角行列とは 正方行列 m[][] が対角行列であるのは、主対角線以外の要素がすべてゼロである場合、かつその場合に限ります。 下図のように、赤色で示された要素が主対角成分(非ゼロ)であり、それ以外の要素はすべてゼロになっているため、この行列は対角行列です。 入出力例 Input: m[3][3] = { {7, 0, 0}, {0, 8, 0}

  2. C++でグラフの隣接行列を実装する方法【サンプルコード付き解説】

    隣接行列とは グラフの隣接行列(Adjacency Matrix)とは、V×Vのサイズを持つ正方行列のことです。ここでVはグラフGの頂点数を表します。行列の行と列にはそれぞれ頂点が対応付けられ、頂点iから頂点jへの辺が存在する場合は、i行目・j列目の要素に1が格納されます(重み付きグラフの場合は、辺の重みなどの非ゼロの値が入ります)。辺が存在しない場合は0が格納されます。 なお、無向グラフの場合、辺は双方向につながりを持つため、隣接行列は必ず対称行列になります。つまり、adj[i][j]とadj[j][i]は常に同じ値となります。 隣接行列表現の計算量 空間計算量: 隣接行列にはO(V²)