๐ Hash table
๐ Hash table ์ ๋ฆฌ
๐ Hash table์ด๋?
- ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ ์ฅํ๊ณ ๊ฒ์ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์๋ฃ๊ตฌ์กฐ
- ํค-๊ฐ(key-value pair) ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉฐ ๋ด๋ถ์ ์ผ๋ก๋ ํด์ ํจ์๋ฅผ ์ด์ฉํด ํค๋ฅผ ํน์ ์์น์ ๋งคํํ๋ค.
- C++ STL(Standard Template Library)์์๋ ์ฃผ๋ก unordered_map ๊ณผ unordered_set ์ผ๋ก ํด์ํ ์ด๋ธ์ ๊ตฌํํ๋ค.
๐ก ํน์ง
1. ๋น ๋ฅธ ๊ฒ์
- ํ๊ท ์ ์ผ๋ก (O(1))์ ์๊ฐ ๋ณต์ก๋๋ก ๊ฒ์, ์ฝ์ , ์ญ์ ๋ฅผ ์ํํ๋ค. ์ต์ ์ ๊ฒฝ์ฐ๋ ์ถฉ๋์ด ๋ง์ ๋ (O(n))์ด๋ค.
2. ํค- ๊ฐ(key-value) ์์ผ๋ก ์ ์ฅ
3. ํด์ ํจ์
- ํค๋ฅผ ํน์ ๋ฒํท์ผ๋ก ๋งคํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค. ํด์ํจ์๊ฐ ์ถฉ๋์ ์ต์ํ ํ ์๋ก ์ฑ๋ฅ์ด ์ฌ๋ผ๊ฐ๋ค. **
๐ป ๊ตฌํ
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<string, int> hash_table {
{"apple", 5},
{"banana", 3},
{"pear", 10}
};
cout << hash_table["apple"] << endl;
//๋ชจ๋ ํค๊ฐ ์ถ๋ ฅํด๋ณด๊ธฐ
//์ถ๋ ฅํ๋ ๋ฐฉ๋ฒ์ ๋๊ฐ์ง๊ฐ ์กด์ฌ
// 1. range-based for loop
for(const auto& pair : hash_table)
{
cout << pair.first << " : " << pair.second << endl;
}
// 2. iterator
for(auto it = hash_table.begin(); it != hash_table.end(); it++)
{
cout << it->first << " : " << it->second << endl;
}
return 0;
}
๐ป ์ฝ๋ ๊ณต๋ถ
unordered_map<string, int> hash_table {
{"apple", 5},
{"banana", 3},
{"pear", 10}
};
- ํด์ ํ ์ด๋ธ์ ์ ๋ ๋ฐฉ๋ฒ์ด๋ค.
- unordered_map<key, value> ํจ์๋ช { };
- ํด์ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ ์์๋๋ก ์ ์ฅํ์ง ์๋๋ค. ๊ทธ๋์ ๋ง์ฝ ์ ๋ถ ์ถ๋ ฅํ๋ค๋ฉด ๋๋ค์ผ๋ก ์ ๋ ฌ๋์ด ์ถ๋ ฅ๋๋ค.
// 1. range-based for loop
for(const auto& pair : hash_table)
{
cout << pair.first << " : " << pair.second << endl;
}
- ๋ฒ์ ์ง์ ํด ๋ฐ๋ณตํด์ ํด์ ํ ์ด๋ธ ๊ฐ๋ค ์ ๋ถ ์ถ๋ ฅํด๋ณด๊ธฐ
- auto ๋ ์๋ ํ์ ์ถ๋ก ์ ํด์ฃผ๋ ํค์๋์ด๋ค. ๋ณ์ ์ ์ธ ์ ์ด๊ธฐํ ๊ฐ์ ํ์ ์ ์๋์ผ๋ก ์ถ๋ก ํ์ฌ ์ปดํ์ผ๋ฌ๊ฐ ๊ฒฐ์ ํ๋ค
- ๋ํ &(reference)๊ฐ ๋ถ์ ์ด์ ๋ ๋ถํ์ํ ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ๋ฅผ ๋ง๊ธฐ ์ํจ์ด๋ค. ๋ง์ฝ hash_table์ ํฌ๊ธฐ๊ฐ ๋งค์ฐ ํฌ๋ค๋ฉด ๋ณต์ฌ๋ฅผ ํ๋๋ฐ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ญ๋น๋๋ฏ๋ก ํ๋ก๊ทธ๋จ์ด ์ ํ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์๋ณธ์ ์ฐธ์กฐํ๋๋ก &(reference)๋ฅผ ๋ถ์ฌ์ค๋ค.
// 2. iterator
for(auto it = hash_table.begin(); it != hash_table.end(); it++)
{
cout << it->first << " : " << it->second << endl;
}
- iterator ๋ฐ๋ณต์๋ฅผ ํตํด ํด์ํ ์ด๋ธ ์ ๋ถ ๋ฝ์๋ณด๊ธฐ
๐ ์ฃผ์ ๋ฉ์๋
- insert() : ์ฝ์
```cpp
#include
#include
int main() { std::unordered_map<int, std::string> umap; umap.insert({1, โappleโ}); umap.insert({2, โbananaโ});
// ํค๊ฐ ์กด์ฌํ๋ฉด ์ฝ์
๋์ง ์์
umap.insert({1, "grape"});
std::cout << umap[1] << std::endl; // apple
return 0; } ``` ์๋ก์ด (key, value) ๋ฅผ ์ฝ์
ํ๋ค.
- operator[] : ํค๋ฅผ ์ฌ์ฉํ์ฌ ์ ๊ทผ
umap[3] = "cherry"; // ์๋ก์ด (3, "cherry") ์ฝ์ std::cout << umap[3] << std::endl; // ์ถ๋ ฅ: cherryํค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ(value)์ ์ ๊ทผ ๋ง์ฝ ํค๊ฐ ์๋ค๋ฉด ๊ธฐ๋ณธ๊ฐ์ ์ฝ์ ํ๊ณ ๋ฐํ
- emplace() : insert()์ ๋น์ทํ์ง๋ง ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํด์ ๋ฃ์
// ๋ฐ๋ก ์์ฑํ๊ณ ๋ฐ๋ก (key, value)๋ฃ์ umap.emplace(4, "mango"); - count() : ํน์ ํค ์กด์ฌ ๊ฒ์
if (umap.count(2)) { std::cout << "Key 2 exists\n"; }๋ฐํ๊ฐ์ด 1 ์ด๋ฉด ์กด์ฌ 0 ์ด๋ฉด ์กด์ฌํ์ง ์๋๋ค๋ ๋ป
- find() : ํค๋ฅผ ์ฐพ์ intertor ๋ฐํ
auto it = umap.find(2); if (it != umap.end()) { std::cout << "Key 2 found: " << it->second << std::endl; }ํค๊ฐ ์กด์ฌํ๋ฉด ํด๋น ํค-๊ฐ์ ํฌ์ธํฐ ๋ฅผ ๋ฐํํ๊ณ ์์ผ๋ฉด operator.end() ๋ฅผ ๋ฐํํ๋ค.
- erase() : ํน์ ํค ์ญ์ ```cpp umap.erase(2); // ํค 2 ์ญ์
// ์ดํฐ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํด ์ญ์ ํ ์๋ ์์ auto it = umap.find(3); if (it != umap.end()) { umap.erase(it); }
- **clear() : ๋ชจ๋ ์์ ์ญ์ **
```cpp
umap.clear();
- size() : ํ์ฌ ํด์ฌํ
์ด๋ธ์ ์์ ๊ฐ์ ๋ฐํ
std::cout << "Size: " << umap.size() << std::endl; - empty() : ๋งต์ด ๋น์ด์๋์ง true or false ๋ก ๋ฐํ
if (umap.empty()) { std::cout << "Hash table is empty" << std::endl; } - begin(), end() : ์ฒซ ๋ฒ์งธ์ ๋ ๋ค์ ์์น ๋ฅผ ๊ฐ๋ฆฌํค๋ ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ฐํ
๐ ์ ๋ฆฌ
c++ ์์ hash table ์ unordered_map ๊ณผ unordered_set ์ผ๋ก ๊ตฌํํ ์ ์๋ค. ๋น ๋ฅธ ๊ฒ์, ์ฝ์ , ์ญ์ ๋ฅผ ์ ๊ณตํ์ง๋ง ์ถฉ๋๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ด๋ฆฌ๊ฐ ์ค์ํ ์์์ด๋ฉฐ, ๋ฐ์ดํฐ ์์๋ฅผ ์ ์งํ๋ ค๋ฉด map์ ์ฌ์ฉํด์ผํ๋ค. (์ฌ๊ธฐ์๋ unordered_map๋ง ๋ค๋ค๋๋ฐ unordered_set์ ์ค๋ณต๋์ง ์์ ๊ณ ์ ํ ํค๋ง ์ ์ฅํ๋ ๋ฐฉ๋ฒ์ด๋ค.)
์ถ๊ฐ ๋ด์ฉ(03-06)
- hash table ์์ ๋ง์ฝ ์ ์ฅ๋์ด ์์ง ์๋ ๊ฐ์ด ๋์จ๋ค๋ฉด ์๋์ ์ผ๋ก 0์ ๊ฐ์ผ๋ก ์ฒ๋ฆฌ ํ๋ค
์ถ๊ฐ ๋ด์ฉ(03-07)
- hash table ์์ ์ธ์๋ก int, char, int ๋ง๊ณ function ํจ์๋ฅผ ์ ์ธํ ์ ์๋ค. leecode ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์