コンテンツにスキップ

22. ハッシュテーブル

ハッシュセット HashSet とハッシュテーブル HashTable の基本的な使い方を学びます。

22.1 ハッシュセットクラス

HashSet<Key> は、std::unordered_set<Key> に相当するクラスです。ハッシュに対応したキーの集合を表現し、キーの追加、削除、検索を効率的に行うことができます。集合内の順序は保証されません。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	// 追加された順序と一覧表示の順序は一致しない
	Print << table;

	while (System::Update())
	{

	}
}

22.2 キーを追加する

.insert(key) でキーを追加することができます。すでに同じキーが存在する場合は、何もしません。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	table.insert(U"Python");

	table.insert(U"C#");

	// すでに存在するため追加されない
	table.insert(U"Java");
	table.insert(U"C#");

	Print << table;

	while (System::Update())
	{

	}
}

22.3 キーの数を調べる

.size() でキーの数を調べることができます。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	table.insert(U"Python");

	table.insert(U"C#");

	table.insert(U"Java");

	table.insert(U"C#");

	Print << table.size();

	Print << table;

	while (System::Update())
	{

	}
}

22.4 指定したキーが存在するかを調べる

.contains(key) で指定したキーが存在するかを調べることができます。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	table.insert(U"Python");

	table.insert(U"C#");

	// "C++" というキーが存在するかを調べる
	Print << table.contains(U"C++");

	// "Ruby" というキーがが存在するかを調べる
	Print << table.contains(U"Ruby");

	while (System::Update())
	{

	}
}

22.5 範囲 for 文で要素にアクセスする

範囲 for 文を使うと、ハッシュセットのすべてのキーにアクセスできます。順序は保証されません。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	table.insert(U"Python");

	table.insert(U"C#");

	// 追加された順序とアクセスの順序は一致しない
	for (const auto& key : table)
	{
		Print << key;
	}

	while (System::Update())
	{

	}
}

22.6 キーを削除する

.erase(key) で指定したキーを削除することができます。

# include <Siv3D.hpp>

void Main()
{
	HashSet<String> table = { U"C++", U"C", U"Java" };

	table.insert(U"Python");

	table.insert(U"C#");

	Print << table;

	// "Python" を削除する
	table.erase(U"Python");

	Print << table;

	while (System::Update())
	{

	}
}

22.7 ハッシュテーブルクラス

HashTable<Key, Value> は、std::unordered_map<Key, Value> に相当するクラスです。ハッシュに対応したキーと値のペアを要素とする集合を表現し、要素の追加、削除、検索を効率的に行うことができます。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
		{ U"pasta", 1 },
		{ U"pizza", 4 },
	};

	// 追加された順序と一覧表示の順序は一致しない
	Print << table;

	while (System::Update())
	{

	}
}

22.8 要素を追加する

.emplace(key, value) でキーと値のペアを追加することができます。すでに同じキーが存在する場合は、何もしません。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
		{ U"pasta", 1 },
		{ U"pizza", 4 },
	};

	table.emplace(U"bulgogi", 2);

	// すでにキーが存在する場合は何もしない
	table.emplace(U"pasta", 500);

	table.emplace(U"pirozhki", 0);

	Print << table;

	while (System::Update())
	{

	}
}

22.9 要素数を調べる

.size() で要素数を調べることができます。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
		{ U"pasta", 1 },
		{ U"pizza", 4 },
	};

	table.emplace(U"bulgogi", 2);

	// すでにキーが存在する場合は何もしない
	table.emplace(U"pasta", 500);

	table.emplace(U"pirozhki", 0);

	Print << table.size();

	Print << table;

	while (System::Update())
	{

	}
}

22.10 要素にアクセスする

[key] で指定したキーに対応する値にアクセスできます。キーが存在しない場合は、新しく要素が追加され、値はデフォルト値で初期化されます。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
	};

	Print << table[U"sushi"];

	Print << U"------";

	++table[U"curry"];

	table[U"hamburger"] = 20;

	Print << table;

	Print << U"------";

	// 存在しないキーを [] で指定すると、新しく要素が追加され、値はデフォルト値で初期化される
    Print << table[U"pasta"];
	++table[U"nachos"];

	Print << table;

	while (System::Update())
	{

	}
}

22.11 指定したキーが存在するかを調べる(contains)

.contains(key) で指定したキーが存在するかを調べることができます。

# include <Siv3D.hpp>

void Main()
{
	const HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
	};

	Print << table.contains(U"sushi");

	// [] ではないため、ここでは pasta は追加されない
	Print << table.contains(U"pasta");

	Print << table;

	while (System::Update())
	{

	}
}

22.12 指定したキーが存在するか調べる(イテレータ)

.find(key) で指定したキーが存在するかを調べることができます。存在する場合は、その要素へのイテレータを返します。存在しない場合は、end() へのイテレータを返します。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
	};

	if (auto it = table.find(U"sushi");
		it != table.end())
	{
		// 存在すれば値を 1 増やす
		++it->second;
	}
	else
	{
		// 存在しなければ要素を追加する
		table.emplace(U"sushi", 1);
	}

	if (auto it = table.find(U"pasta");
		it != table.end())
	{
		// 存在すれば値を 1 増やす
		++it->second;
	}
	else
	{
		// 存在しなければ要素を追加する
		table.emplace(U"pasta", 1);
	}

	Print << table;

	while (System::Update())
	{

	}
}

22.13 範囲 for 文で要素にアクセスする

範囲 for 文を使うと、ハッシュテーブルのすべての要素にアクセスできます。順序は保証されません。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
		{ U"pasta", 1 },
		{ U"pizza", 4 },
	};

	// 構造化束縛を使う
	for (auto&& [key, value] : table)
	{
		Print << key << U": " << value;
	}

	Print << U"------";

	// pair を使う
	for (auto&& elem : table)
	{
		Print << elem.first << U": " << elem.second;
	}

	while (System::Update())
	{

	}
}

22.14 要素を削除する

.erase(key) で指定したキーに対応する要素を削除できます。

# include <Siv3D.hpp>

void Main()
{
	HashTable<String, int32> table =
	{
		{ U"curry", 3 },
		{ U"sushi", 3 },
		{ U"hamburger", 0 },
		{ U"pasta", 1 },
		{ U"pizza", 4 },
	};

	table.erase(U"pizza");

	table.erase(U"sushi");

	Print << table;

	while (System::Update())
	{

	}
}