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

C++で配列から要素を削除する方法:2回の走査と1回の走査の違いを解説

はじめに

C++で配列から特定の要素を削除する場合、「検索」と「詰め替え(シフト)」をどのタイミングで行うかによって、主に2つのアプローチがあります。1つは検索とシフトを別々に行う「2回の走査」、もう1つは両方を同時に処理する「1回の走査」です。ここでは、それぞれの考え方と実装方法をサンプルコード付きで解説します。

その1:2回の走査で削除する

まず、元の配列と、検索・削除したい要素を定義します。

int ele = 5;
int arr[] = {1, 2, 3, 4};

次に、forループで配列を先頭から走査し、目的の要素が格納されている位置を特定します。

for (i = 0; i < length; i++)
    if (arr[i] == ele) break;

要素の位置が見つかったら、その位置より右側にある要素をすべて1つずつ左へ移動させます。これにより、削除したい要素は後ろの要素で上書きされ、配列の長さも1つ減ります。

if (i < length) {
    length--;
    for (int j = i; j < length; j++)
        arr[j] = arr[j + 1];
}

サンプルコード(全体)

以下は、2回の走査によって配列内の要素を削除する完全な実装例です。

#include<iostream>
using namespace std;

int main() {
    int arr[] = {11, 15, 6, 8, 9, 10};
    int length = sizeof(arr) / sizeof(arr[0]);
    int ele = 6;

    int i;
    // 1回目の走査:要素の位置を検索
    for (i = 0; i < length; i++)
        if (arr[i] == ele) break;

    // 見つかった場合:2回目の走査で左詰め
    if (i < length) {
        length--;
        for (int j = i; j < length; j++)
            arr[j] = arr[j + 1];
    }

    cout << "The array after deletion is " << endl;
    for (int i = 0; i < length; i++)
        cout << arr[i] << " ";

    return 0;
}

実行結果

上記のコードを実行すると、次のような出力が得られます。

The array after deletion is
11 15 8 9 10

その2:1回の走査で削除する

こちらの方法では、検索とシフト処理を1つのループ内で同時に行います。まず、元の配列と削除対象の要素を定義します。

int ele = 15;
int arr[] = {11, 15, 6, 8, 9, 10};

次に、要素が見つかったかどうかを示すbool型変数foundと、見つかった場合にその位置を保持するint型変数posを宣言します。

bool found = false;
int pos = -1;

そして、ループで配列を1回だけ走査しながら、要素が見つかった時点でその位置を記録し、それ以降は各反復ごとに要素を左へシフトしていきます。

for (int i = 0; i < length; i++) {
    if (pos != -1) {
        arr[pos] = arr[pos + 1];
        pos++;
    }
    else if (arr[i] == ele) {
        pos = i;
        found = true;
    }
}

サンプルコード(全体)

以下は、わずか1回の走査で配列から要素を削除する完全な実装例です。

#include<iostream>
using namespace std;

int main() {
    int arr[] = {11, 15, 6, 8, 9, 10};
    int length = sizeof(arr) / sizeof(arr[0]);
    int ele = 6;

    bool found = false;
    int pos = -1;

    // 検索とシフトを同時に実施
    for (int i = 0; i < length; i++) {
        if (pos != -1) {
            arr[pos] = arr[pos + 1];
            pos++;
        }
        else if (arr[i] == ele) {
            pos = i;
            found = true;
        }
    }

    if (found)
        length--;

    cout << "The array after deletion is " << endl;
    for (int i = 0; i < length; i++)
        cout << arr[i] << " ";

    return 0;
}

実行結果

上記のコードを実行すると、次のような出力が得られます。

The array after deletion is
11 15 8 9 10

まとめ

どちらの方法でも最終的な結果は同じですが、1回の走査の方がループの回数が少なく、大きな配列では効率的です。一方、2回の走査方式はロジックが単純で理解しやすいというメリットがあります。パフォーマンスが重視される場面では1回の走査方式を、可読性を優先したい場面では2回の走査方式を選ぶとよいでしょう。

  1. C++で条件演算子を使わずに配列の最大要素を求める方法

    問題の概要 いくつかの要素を含む配列 A があるとします。この配列 A の中から最大の要素を見つけたいのですが、条件演算子を一切使用してはならないという制約が課されています。例えば、A = [12, 63, 32, 24, 78, 56, 20] という配列が与えられた場合、求める最大要素は 78 です。 解決のアプローチ:ビット演算を活用する この問題を解くカギとなるのがビット単位のAND演算です。基本的な考え方は次の通りです。 まず、すべてのビットが 1 になっている特殊な値 INT_MAX を配列に 1 つ追加します。 続いて、最上位ビット(第31ビット)から最下位ビット(第0ビット)

  2. C++でSTLを使って配列の積を求める方法

    C++では、STL(標準テンプレートライブラリ)のaccumulate関数を利用することで、配列内のすべての要素の積を簡潔に求めることができます。ここでは、その具体的な実装例を紹介します。 アルゴリズム 開始 配列の各要素の値を初期化する。 ユーザー定義関数 accumulate を呼び出し、配列全体の積を取得する。 計算結果を出力する。 終了 サンプルコード #include <iostream> #include <numeric> using namespace std; int ProductOfArray(int p[], int n)