์ ์ ๊ฐ๋ฐ์ ๊ธฐ์ ๋ฉด์ C++ ์์ฝ๋ฉ : Array, Vector, List, Stack, Queue, Tree, Heap, Hash ๋ชจ๋ ์์ด ๊ตฌํ
1. Vector, List, Map ์ ๋ํด์ ์ค๋ช ํด ๋ณด์ธ์.
stl์ ๋ฑ๋ก๋์ด ์๋ ์๋ฃ๊ตฌ์กฐ๋ค๋ก์ vector๋ ๋์ ๋ฐฐ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉฐ, List๋ ๋๋ธ๋งํฌ๋ ๋ฆฌ์คํธ๋ก ์ด๋ฃจ์ด์ ธ์์ต๋๋ค. Map์ Key์ Value๋ฅผ ์์ผ๋ก ์ด๋ฃจ๋ฉฐ ๋ ๋๋ธ๋ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ด์ ๋น ๋ฅธ ํ์์๋๋ฅผ ์๋ํฉ๋๋ค.
2. Vector, List ์ ์ฐจ์ด์ ๋ํด์ ์ค๋ช ํ์ธ์.
vector๋ ๋์ ๋ฐฐ์ด์ ํด๋์ค ํฌํ๋ฆฟ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
vector๊ฐ์ฒด๋ ์์๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์ญ์ ๋ ๋๋ง๋ค ์๋์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌํ ๋นํ์ฌ ํฌ๊ธฐ๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
list๋ ์ด์ค์ฐ๊ฒฐ๋ฆฌ์คํธ์ ํด๋์ค ํฌํ๋ฆฟ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
์ด ์ปจํ ์ด๋๋ ๋ชจ๋ ์์์์ ์๋ฐฉํฅ ์ ๊ทผ, ๋น ๋ฅธ ์ฝ์ ๊ณผ ์ญ์ ๋ฅผ ํ ์ ์์ง๋ง, ์์ ์ ๊ทผ์ ๋ถ๊ฐํฉ๋๋ค.
๋ํ ๋ฆฌ์คํธ๋ฅผ ๊ตฌ์ฑํ๋ ๋งํฌ(link)๋ ํฌ์ธํฐ์ด๋ฏ๋ก, ๋ค์๊ณผ ๊ฐ์ ํน์ ์์ ์ ๋งํฌ๋ง ์ฌ๋ฐฐ์นํ๋ ๊ฒ์ผ๋ก ์์ฃผ ๋น ๋ฅด๊ฒ ์ํํ ์ ์์ต๋๋ค.
3. Tree ์ ๋ํด์ ์๋๋๋ก ๋งํ์์ค.
ํธ๋ฆฌ๋ ํ์์์์ ๋ฐ์ด๋ ์ฑ๋ฅ์ ๊ฐ์ง ์ปจํ ์ด๋๋ก์ ๊ณ์ธต์ ์ธ ๋ฐ์ดํฐ ๊ฒ์์ ์๋์ ์ธ ์ฑ๋ฅ์ ๋ณด์ ๋๋ค.
์ด์งํธ๋ฆฌ ๋ ๋๋ธ๋ํธ๋ฆฌ, ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ, AVLํธ๋ฆฌ ๋ฑ ์ฌ๋ฌ ์ข ๋ฅ์ ํธ๋ฆฌ๊ฐ ์๊ณ ,
์ด์งํธ๋ฆฌ๋ ๊ฐ๊ฐ์ ๋ ธ๋๊ฐ ์ต๋ ๋๊ฐ์ ์์๋ ธ๋๋ฅผ ๊ฐ์ง๋ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก์
๋ ธ๋๋น ๋๊ฐ์ ์์๋ ธ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ ์์ ์ด์งํธ๋ฆฌ๋ก ๊ตฌ์ฑ์ด ๋๋ค๋ฉด ์์ฃผ ์ข์ ํธ๋ฆฌ๊ฐ ๋์ง๋ง, ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ ํธ๋ฆฌ๋ฅผ ์ฐ๋๋๋ง ๋ชปํ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ ํ ์๋ ์์ต๋๋ค.
์ด๋ฌํ ๋จ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด์ ๋ฐ์ ๋ ํํ๊ฐ ๋ ๋๋ธ๋ํธ๋ฆฌ๊ฐ ์๋๊ฒ์ผ๋ก ์๊ณ ์์ต๋๋ค.
Array
C++์์ ๊ณ ์ ํฌ๊ธฐ์ ๋ฐฐ์ด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์๋ฉ๋๋ค. ํ์ง๋ง ํด๋์ค๋ฅผ ๋ง๋ค์ด ๋ค๋ฃจ๋ ๊ฒ์ ์ํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. C++์์๋ ๊ณ ์ ํฌ๊ธฐ ๋ฐฐ์ด์ด ์๋์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์๋ฉธ์๊ฐ ํ์ํ์ง ์์ต๋๋ค.
template<typename T, size_t S>
class StaticArray {
private:
T m_Array[S]; // ๊ณ ์ ํฌ๊ธฐ์ ๋ฐฐ์ด
public:
T& operator[](size_t index) {
return m_Array[index];
}
const T& operator[](size_t index) const {
return m_Array[index];
}
size_t Size() const { return S; }
};
Vector
std::vector์ ๊ฐ์ ๋์ ๋ฐฐ์ด์ ๊ฐ๋จํ๊ฒ ๊ตฌํํ๋ ๊ฒ์ ์กฐ๊ธ ๋ ๋ณต์กํ์ง๋ง, ๋ค์์ ๊ทธ ๊ธฐ๋ณธ์ ์ธ ํํ์ ๋๋ค.
template<typename T>
class Vector {
private:
T* data;
size_t capacity;
size_t size;
void reallocate(size_t newCapacity) {
T* newData = new T[newCapacity];
size_t newSize = size > newCapacity ? newCapacity : size;
for (size_t i = 0; i < newSize; ++i) {
newData[i] = std::move(data[i]);
}
delete[] data;
data = newData;
capacity = newCapacity;
size = newSize;
}
public:
Vector() : data(nullptr), capacity(0), size(0) {}
void push_back(const T& value) {
if (size >= capacity) {
size_t newCapacity = capacity == 0 ? 1 : capacity * 2;
reallocate(newCapacity);
}
data[size++] = value;
}
~Vector() {
delete[] data;
}
};
List
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ ธ๋๋ค์ด ํฌ์ธํฐ๋ฅผ ํตํด ์ฐ๊ฒฐ๋์ด ์๋ ๊ตฌ์กฐ์ ๋๋ค. ๋ค์์ ๋จ์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Singly Linked List)์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ์ ๋๋ค.
template<typename T>
class List {
private:
struct Node {
T value;
Node* next;
Node(const T& val) : value(val), next(nullptr) {}
};
Node* head;
public:
List() : head(nullptr) {}
void push_front(const T& value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
}
~List() {
Node* current = head;
while (current != nullptr) {
Node* temp = current;
current = current->next;
delete temp;
}
}
};
Stack
Stack์ LIFO(Last In, First Out) ์ ์ฑ ์ ๋ฐ๋ฅด๋ ์๋ฃ๊ตฌ์กฐ๋ก, ๊ฐ์ฅ ๋ง์ง๋ง์ ๋ค์ด์จ ์์๊ฐ ๊ฐ์ฅ ๋จผ์ ๋๊ฐ๋๋ค. ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ๊ตฌํํ ์ ์์ต๋๋ค.
template<typename T>
class Stack {
private:
struct Node {
T value;
Node* next;
Node(const T& val) : value(val), next(nullptr) {}
};
Node* topNode;
public:
Stack() : topNode(nullptr) {}
void push(const T& value) {
Node* newNode = new Node(value);
newNode->next = topNode;
topNode = newNode;
}
~Stack() {
while (topNode != nullptr) {
Node* temp = topNode;
topNode = topNode->next;
delete temp;
}
}
};
Queue
Queue๋ FIFO(First In, First Out) ์ ์ฑ ์ ๋ฐ๋ฅด๋ ์๋ฃ๊ตฌ์กฐ๋ก, ๊ฐ์ฅ ๋จผ์ ๋ค์ด์จ ์์๊ฐ ๊ฐ์ฅ ๋จผ์ ๋๊ฐ๋๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ ์ ์์ต๋๋ค.
template<typename T>
class Queue {
private:
struct Node {
T value;
Node* next;
Node(const T& val) : value(val), next(nullptr) {}
};
Node* frontNode;
Node* backNode;
public:
Queue() : frontNode(nullptr), backNode(nullptr) {}
void enqueue(const T& value) {
Node* newNode = new Node(value);
if (backNode) {
backNode->next = newNode;
}
backNode = newNode;
if (!frontNode) {
frontNode = backNode;
}
}
~Queue() {
while (frontNode != nullptr) {
Node* temp = frontNode;
frontNode = frontNode->next;
delete temp;
}
}
};
Binary Tree
template<typename T>
class BinaryTree {
private:
struct Node {
T value;
Node *left, *right;
Node(T val) : value(val), left(nullptr), right(nullptr) {}
};
Node* root;
void Clear(Node* node) {
if (node != nullptr) {
Clear(node->left);
Clear(node->right);
delete node;
}
}
public:
BinaryTree() : root(nullptr) {}
// ์ด์ง ํธ๋ฆฌ์ ์์๋ฅผ ์ฝ์
ํ๊ณ ์ญ์ ํ๋ ๋ฑ์ ๋ฉ์๋ ๊ตฌํ ํ์
~BinaryTree() {
Clear(root);
}
};
Binary Heap
์ด์ง ํ์ ๋ฐฐ์ด์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์์ ์ด์ง ํธ๋ฆฌ์ ๋๋ค. ์ฌ๊ธฐ์๋ ์ต๋ ํ(Max Heap)์ ๊ฐ๋จํ ๊ตฌํ์ ๋ณด์ฌ๋๋ฆฝ๋๋ค.
template<typename T>
class BinaryHeap {
private:
std::vector<T> heap;
void HeapifyDown(int index) {
int left = 2 * index + 1;
int right = 2 * index + 2;
int largest = index;
if (left < heap.size() && heap[left] > heap[largest])
largest = left;
if (right < heap.size() && heap[right] > heap[largest])
largest = right;
if (largest != index) {
std::swap(heap[index], heap[largest]);
HeapifyDown(largest);
}
}
void HeapifyUp(int index) {
while (index != 0 && heap[(index - 1) / 2] < heap[index]) {
std::swap(heap[(index - 1) / 2], heap[index]);
index = (index - 1) / 2;
}
}
public:
void Insert(T element) {
heap.push_back(element);
HeapifyUp(heap.size() - 1);
}
T ExtractMax() {
if (heap.size() == 0)
throw std::out_of_range("Heap is empty");
T root_value = heap[0];
heap[0] = heap.back();
heap.pop_back();
HeapifyDown(0);
return root_value;
}
bool IsEmpty() const {
return heap.empty();
}
};
Binary Search Tree
์ด์ง ํ์ ํธ๋ฆฌ
template<typename T>
class BinarySearchTree {
private:
struct Node {
T value;
Node *left, *right;
Node(const T& val) : value(val), left(nullptr), right(nullptr) {}
};
Node* root;
void clear(Node* node) {
if (node) {
clear(node->left);
clear(node->right);
delete node;
}
}
public:
BinarySearchTree() : root(nullptr) {}
~BinarySearchTree() {
clear(root);
}
};
Priority Queue - Max Heap
MaxPriorityQueue ํด๋์ค๋ ์์๋ฅผ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ์ฌ, ๊ฐ์ฅ ํฐ ์์๊ฐ ํญ์ ๋งจ ์์ ์ค๋๋ก ํฉ๋๋ค.
heapifyUp๊ณผ heapifyDown ๋ฉ์๋๋ ํ ์์ฑ์ ์ ์งํ๊ธฐ ์ํด ์์๋ฅผ ์ ์ ํ ์์น๋ก ์ด๋์ํต๋๋ค. push ๋ฉ์๋๋ ์๋ก์ด ์์๋ฅผ ํ์ ์ถ๊ฐํ๊ณ , pop ๋ฉ์๋๋ ํ์์ ์ต๋๊ฐ ๋๋ ์ต์๊ฐ์ ์ ๊ฑฐํ๊ณ ๋ฐํํฉ๋๋ค. top ๋ฉ์๋๋ ํ์ ์ต๋๊ฐ ๋๋ ์ต์๊ฐ์ ์กฐํํ์ง๋ง ์ ๊ฑฐํ์ง๋ ์์ต๋๋ค. empty์ size ๋ฉ์๋๋ ํ์ด ๋น์ด ์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐํํ๊ณ , ํ์ ํฌ๊ธฐ๋ฅผ ๋ฐํํฉ๋๋ค.
#include <vector>
#include <algorithm> // For std::swap
#include <stdexcept> // For std::out_of_range
template<typename T>
class MaxPriorityQueue {
private:
std::vector<T> heap;
void heapifyDown(int currentIdx) {
int leftIdx = 2 * currentIdx + 1;
int rightIdx = 2 * currentIdx + 2;
int largestIdx = currentIdx;
if (leftIdx < heap.size() && heap[leftIdx] > heap[largestIdx]) {
largestIdx = leftIdx;
}
if (rightIdx < heap.size() && heap[rightIdx] > heap[largestIdx]) {
largestIdx = rightIdx;
}
if (largestIdx != currentIdx) {
std::swap(heap[currentIdx], heap[largestIdx]);
heapifyDown(largestIdx);
}
}
void heapifyUp(int currentIdx) {
while (currentIdx != 0 && heap[(currentIdx - 1) / 2] < heap[currentIdx]) {
std::swap(heap[(currentIdx - 1) / 2], heap[currentIdx]);
currentIdx = (currentIdx - 1) / 2;
}
}
public:
void push(const T& value) {
heap.push_back(value);
heapifyUp(heap.size() - 1);
}
T pop() {
if (heap.empty()) throw std::out_of_range("PriorityQueue is empty");
T maxValue = heap[0];
heap[0] = heap.back();
heap.pop_back();
heapifyDown(0);
return maxValue;
}
const T& top() const {
if (heap.empty()) throw std::out_of_range("PriorityQueue is empty");
return heap[0];
}
bool empty() const {
return heap.empty();
}
size_t size() const {
return heap.size();
}
};
Priority Queue - Min Heap
Priority Queue๋ ๋ด๋ถ์ ์ผ๋ก ๋ณดํต ์ด์ง ํ(Binary Heap) ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. C++์์๋ ์ด๋ฅผ std::vector๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ ์ ์์ผ๋ฉฐ, ๊ธฐ๋ณธ์ ์ผ๋ก ์ต๋ ํ(Max Heap)์ ์ฌ์ฉํฉ๋๋ค.
MinPriorityQueue ํด๋์ค๋ ์์๋ฅผ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ์ฌ, ๊ฐ์ฅ ์์ ์์๊ฐ ํญ์ ๋งจ ์์ ์ค๋๋ก ํฉ๋๋ค.
heapifyUp๊ณผ heapifyDown ๋ฉ์๋๋ ํ ์์ฑ์ ์ ์งํ๊ธฐ ์ํด ์์๋ฅผ ์ ์ ํ ์์น๋ก ์ด๋์ํต๋๋ค. push ๋ฉ์๋๋ ์๋ก์ด ์์๋ฅผ ํ์ ์ถ๊ฐํ๊ณ , pop ๋ฉ์๋๋ ํ์์ ์ต๋๊ฐ ๋๋ ์ต์๊ฐ์ ์ ๊ฑฐํ๊ณ ๋ฐํํฉ๋๋ค. top ๋ฉ์๋๋ ํ์ ์ต๋๊ฐ ๋๋ ์ต์๊ฐ์ ์กฐํํ์ง๋ง ์ ๊ฑฐํ์ง๋ ์์ต๋๋ค. empty์ size ๋ฉ์๋๋ ํ์ด ๋น์ด ์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐํํ๊ณ , ํ์ ํฌ๊ธฐ๋ฅผ ๋ฐํํฉ๋๋ค.
#include <vector>
#include <algorithm> // For std::swap
#include <stdexcept> // For std::out_of_range
template<typename T>
class MinPriorityQueue {
private:
std::vector<T> heap;
void heapifyDown(int currentIdx) {
int leftIdx = 2 * currentIdx + 1;
int rightIdx = 2 * currentIdx + 2;
int smallestIdx = currentIdx;
if (leftIdx < heap.size() && heap[leftIdx] < heap[smallestIdx]) {
smallestIdx = leftIdx;
}
if (rightIdx < heap.size() && heap[rightIdx] < heap[smallestIdx]) {
smallestIdx = rightIdx;
}
if (smallestIdx != currentIdx) {
std::swap(heap[currentIdx], heap[smallestIdx]);
heapifyDown(smallestIdx);
}
}
void heapifyUp(int currentIdx) {
while (currentIdx != 0 && heap[(currentIdx - 1) / 2] > heap[currentIdx]) {
std::swap(heap[(currentIdx - 1) / 2], heap[currentIdx]);
currentIdx = (currentIdx - 1) / 2;
}
}
public:
void push(const T& value) {
heap.push_back(value);
heapifyUp(heap.size() - 1);
}
T pop() {
if (heap.empty()) throw std::out_of_range("PriorityQueue is empty");
T minValue = heap[0];
heap[0] = heap.back();
heap.pop_back();
heapifyDown(0);
return minValue;
}
const T& top() const {
if (heap.empty()) throw std::out_of_range("PriorityQueue is empty");
return heap[0];
}
bool empty() const {
return heap.empty();
}
size_t size() const {
return heap.size();
}
};
Unordered Map
template<typename KeyType, typename ValueType>
class UnorderedMap {
private:
struct Node {
KeyType key;
ValueType value;
Node* next;
Node(const KeyType& key, const ValueType& value) : key(key), value(value), next(nullptr) {}
};
std::vector<Node*> buckets;
size_t bucketCount;
size_t GetBucketIndex(const KeyType& key) const {
std::hash<KeyType> hashFn;
return hashFn(key) % bucketCount;
}
public:
UnorderedMap(size_t numBuckets) : bucketCount(numBuckets) {
buckets.resize(bucketCount, nullptr);
}
void insert(const KeyType& key, const ValueType& value) {
size_t bucketIdx = GetBucketIndex(key);
Node* newNode = new Node(key, value);
newNode->next = buckets[bucketIdx];
buckets[bucketIdx] = newNode;
}
// UnorderedMap์ ๋๋จธ์ง ๊ตฌํ ๋ถ๋ถ (๊ฒ์, ์ญ์ ๋ฑ)
~UnorderedMap() {
for (Node* head : buckets) {
while (head != nullptr) {
Node* temp = head;
head = head->next;
delete temp;
}
}
}
};
๋ฒ์ธ) Unordered Map UPGRADE
์ฌ๊ธฐ์๋ ์ฒด์ด๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ถฉ๋์ ํด๊ฒฐํ๋ ๊ธฐ๋ณธ์ ์ธ unordered_map์ ๊ตฌํํ๊ฒ ์ต๋๋ค. ์ด ๊ตฌํ์ ํด์ ํ ์ด๋ธ์ ํต์ฌ ์์ด๋์ด๋ฅผ ํฌํจํ์ง๋ง, ์ค์ ํ๋ก๋์ ํ๊ฒฝ์์ ์ฌ์ฉํ๊ธฐ์๋ ๋ ๋ง์ ์ต์ ํ์ ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
์ด ์ฝ๋๋ UnorderedMap์ ์ํ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค.
- ์ฒด์ด๋(Chaining): ๊ฐ ๋ฒํท์ std::list<KeyValuePair>๋ฅผ ์ฌ์ฉํ์ฌ ํค-๊ฐ ์์ ์ ์ฅํฉ๋๋ค. ์ด๋ฅผ ํตํด ํด์ ์ถฉ๋์ ํด๊ฒฐํฉ๋๋ค.
- ํด์ ํจ์(Hash Function): ๊ธฐ๋ณธ ํด์ ํจ์๋ก std::hash<KeyType>๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ์ฌ์ฉ์ ์ ์ ํ์ ์ ๋ํด ํน์ํ๋ ์ ์์ต๋๋ค.
- ์ฌํด์(Rehashing): ์์์ ์๊ฐ ๋ฒํท์ ์์ 75%๋ฅผ ์ด๊ณผํ๋ฉด, ๋ฒํท ๋ฐฐ์ด์ ํฌ๊ธฐ๋ฅผ ๋ ๋ฐฐ๋ก ๋๋ฆฝ๋๋ค.
insert, at, size, contains ๋ฑ์ ๊ธฐ๋ณธ์ ์ธ ๋ฉ์๋๋ฅผ ํฌํจํฉ๋๋ค. ์ค์ ์ฌ์ฉ์ ์ํด์๋ ๋ ๋ง์ ์์ธ ์ฒ๋ฆฌ, ์ดํฐ๋ ์ดํฐ ์ง์, ๋ณต์ฌ ๋ฐ ์ด๋ ์์ฑ์ ๋ฐ ํ ๋น ์ฐ์ฐ์์ ๊ตฌํ ๋ฑ์ด ํ์ํ ์ ์์ต๋๋ค.
#include <list>
#include <vector>
#include <functional>
#include <stdexcept>
template<typename KeyType, typename ValueType, typename Hash = std::hash<KeyType>>
class UnorderedMap {
private:
struct KeyValuePair {
KeyType key;
ValueType value;
KeyValuePair(const KeyType& key, const ValueType& value) : key(key), value(value) {}
};
std::vector<std::list<KeyValuePair>> buckets;
Hash hasher;
size_t numElements;
size_t getBucketIndex(const KeyType& key) const {
return hasher(key) % buckets.size();
}
void rehash(size_t newBucketCount) {
std::vector<std::list<KeyValuePair>> newBuckets(newBucketCount);
for (auto& bucket : buckets) {
for (auto& kv : bucket) {
size_t newBucketIndex = hasher(kv.key) % newBucketCount;
newBuckets[newBucketIndex].push_back(kv);
}
}
buckets = std::move(newBuckets);
}
public:
UnorderedMap(size_t bucketCount = 8) : buckets(bucketCount), numElements(0) {}
void insert(const KeyType& key, const ValueType& value) {
size_t bucketIndex = getBucketIndex(key);
for (auto& kv : buckets[bucketIndex]) {
if (kv.key == key) {
kv.value = value;
return;
}
}
buckets[bucketIndex].emplace_back(key, value);
numElements++;
if (numElements > buckets.size() * 0.75) { // Load factor of 0.75 for rehashing
rehash(buckets.size() * 2);
}
}
ValueType& at(const KeyType& key) {
size_t bucketIndex = getBucketIndex(key);
for (auto& kv : buckets[bucketIndex]) {
if (kv.key == key) {
return kv.value;
}
}
throw std::out_of_range("Key not found");
}
size_t size() const {
return numElements;
}
bool contains(const KeyType& key) const {
size_t bucketIndex = getBucketIndex(key);
for (const auto& kv : buckets[bucketIndex]) {
if (kv.key == key) {
return true;
}
}
return false;
}
// ์ถ๊ฐ์ ์ธ ๋ฉ์๋ (์ญ์ , ํฌ๊ธฐ ์กฐ์ ๋ฑ)๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
};