【C++】std::listの使い方について詳しく解説

listは、双方向リストを実現するコンテナであり、要素の挿入や削除が高速に行えることが特徴です。

本記事では、listの基本的な使い方から応用的な使い方まで詳しく解説します。

目次

listとは

listは、C++のSTL(Standard Template Library)に含まれるコンテナの一つで、双方向リストを実現するためのクラスです。

listは、要素の追加や削除が高速に行えることが特徴であり、挿入や削除時に他の要素への影響が少ないため、大量のデータを扱う場合に効率的です。

また、イテレータを使用して要素を順番に処理することも可能です。

以下では、listの基本的な使い方について説明します。

listの基本的な使い方

要素の追加

listに要素を追加する方法は、push_back()push_front()を使用する方法があります。

#include <iostream>
#include <list>

using namespace std;

int main()
{
    list<int> my_list;
    my_list.push_back(1); // 末尾に1を追加
    my_list.push_front(2); // 先頭に2を追加
    
    return 0;
}

上記の例では、my_listという名前の空のリストを作成し、その後push_back()push_front()メソッドで要素を追加しています。

要素の取得

listから要素を取得する方法は、front()back()を使用する方法などがあります。

#include <iostream>
#include <list>

int main()
{
    std::list<int> my_list= { 10, 20, 30 };
    int first = my_list.front(); //最初の要素(10)を取得
    int last = my_list.back();   //最後の要素(30)を取得

    std::cout << "最初の要素:" << first << std::endl;
    std::cout << "最後の要素:" << last << std::endl;


    //ループ処理させて取得することも可能
    for (auto i : my_list)
        std::cout << i << " ";

}
最初の要素:10
最後の要素:30
10 20 30

listの要素に順番にアクセスする場合、for(auto 変数名 : リストの変数)の形式でループ処理ができるため、効率よくで要素にアクセスすることが可能です。

要素の削除

listから要素を削除する方法は、erase()メソッドやremove()メソッドがあります。

erase()メソッドは指定した位置または範囲内の要素を削除します。

remove()メソッドは指定した値と一致する全ての要素を削除します。

#include <iostream>
#include <list>

using namespace std;

int main()
{
    list<int> my_list = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };

    // 要素番号2(3番目)から3つ分(3,4,5)削除
    auto it = my_list.begin();
    advance(it, 2);
    my_list.erase(it, next(it, 3));

    // 値が2である全ての要素を削除
    my_list.remove(2);

    for (auto i : my_list)
        std::cout << i << " ";

    return 0;
}
1 4 3 1

上記の例では、my_listという名前で初期値{1,2,3,4,5}が設定されたリストを作成し、erase()メソッドで指定した範囲内(3番目から3つ分)およびremove()メソッドで値が3である全ての要素が削除されます。

要素の検索

listから特定の値や条件に合致する要素を検索する場合は、find_if()関数やcount_if()関数などが利用可能です。

find_if()関数は条件式(ラムダ式も可能)に合致する最初に見つかったイテレーターを返します。

count_if()関数は条件式に合致する個数をカウントして返します。

#include <iostream>
#include <algorithm>
#include <list>

using namespace std;

bool is_even(int i)
{
    return (i % 2) == 0;
}

int main()
{
    list<int> l = { 11,12,13,14 };

    auto it = find_if(l.begin(), l.end(), is_even);

    if (it != l.end())
        cout << "最初に見つかった偶数の値: " << *it << endl;
    else
        cout << "偶数が見つかりませんでした" << endl;

    int count = count_if(l.begin(), l.end(), is_even);

    cout << "偶数の個数: " << count << endl;

    return 0;
}
最初に見つかった偶数の値: 12
偶数の個数: 2

上記例では、偶数判定処理を行うis_even関数が定義されています。

条件式を関数化できるため、複雑な条件による検索や要素数のカウントも自由に行うことが可能です。

listの高度な使い方

listは、要素を追加・削除することが容易であるため、多くの場面で利用されます。

しかし、listにはそれだけではなく、高度な機能も備わっています。

以下では、イテレータの利用方法や要素のソート方法、結合・分割方法について解説します。

イテレータの利用

イテレータとは、コンテナ内の要素を順番にアクセスするためのオブジェクトです。listでも同様にイテレータを使用することができます。

#include <iostream>
#include <list>

int main() {
    std::list<int> my_list = {1, 2, 3, 4, 5};

    // イテレータを使用して全要素を出力
    for (auto itr = my_list.begin(); itr != my_list.end(); ++itr) {
        std::cout << *itr << " ";
    }
    std::cout << std::endl;

    return 0;
}
1 2 3 4 5

上記コードでは、my_list.begin()からmy_list.end()までイテレータを使用して全要素を出力しています。*itrで現在指している要素にアクセスし、++itrで次の要素へ移動しています。

要素のソート

listはsort関数を使用することで簡単にソートすることができます。

sort関数は、通常は昇順にソートされますが、greater<型名>()を第二引数に渡すことで降順にソートすることが実現可能です。

#include <iostream>
#include <list>
#include <algorithm>

int main() {
    std::list<int> my_list = {5, 3, 1, 4, 2};

    // 昇順ソート
    my_list.sort();
    for (auto itr = my_list.begin(); itr != my_list.end(); ++itr) {
        std::cout << *itr << " ";
    }
    std::cout << std::endl;

    // 降順ソート
    my_list.sort(std::greater<int>());
    for (auto itr = my_list.begin(); itr != my_list.end(); ++itr) {
        std::cout << *itr << " ";
    }
    std::cout << std::endl;

    return 0;
}
1 2 3 4 5
5 4 3 2 1

上記コードでは、my_list.sort()で昇順ソートし、次のソートではstd::greater<int>()を渡すことで降順ソートしています。

要素の結合

複数のリストを結合する場合はsplice関数を使用します。

splice関数は第一引数に挿入位置(イテレータ)、第二引数以降に挿入したいリストまたは範囲(イテレータ)を指定します。

以下では2つのリストa,bを作成し、aリスト末尾からbリスト全体を結合しています。

#include <iostream>
#include <list>

int main() {
  	std::list<int> a = {1,2};
  	std::list<int> b = {3,4};

  	a.splice(a.end(), b);

  	for(auto i : a){
  		std::cout<<i<<" ";
  	}
  	std::cout<<std::endl;

  	return 0;
}
1 2 3 4

上記コードではa.splice(a.end(), b)でaリスト末尾からbリスト全体が結合されています。

目次