HashtableImplementationByC

Implement hashtable by C.

๐Ÿ’๐Ÿปโ€โ™‚๏ธ ๊ตฌํ˜„ํ•˜๊ธฐ ์•ž์„œ

ํ•ด์‹œํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช…

ํ•ด์‹œํ…Œ์ด๋ธ”์€ ๋ฐ์ดํ„ฐ์˜ ์–‘์ด ๋งŽ์„ ๊ฒฝ์šฐ ์ƒ๊ธฐ๋Š” ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰์— ๋Œ€ํ•œ ์—ฐ์‚ฐ๊ณผ์ •์„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. key๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ value๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. input ์œผ๋กœ key๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ํ•ด์‰ฌ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•œ ํ•ด์‰ฌ ์ธ๋ฑ์Šค๊ฐ€ ๋‚˜์˜ค๊ณ  ํ•ด๋‹น ์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ๋น ๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„ ๋“ค์–ด๊ฐ€๋Š” ๊ตฌ์กฐ์ด๋‹ค. ๊ทธ๋ฆผ์„ ๋ณด์ž. ํ‚ค์™€ ํ•ด์‹œํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์–ป์€ ํ•ด์‹œ ์ธ๋ฑ์Šค๋กœ Bucket์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ทธ ๋’ค์— ํ‚ค์™€ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋œ ๋…ธ๋“œ๋ฅผ ๋ฒ„์ผ“ ๋’ค์— ๋ถ™์ด๋Š” ํ˜•์‹์ด๋‹ค. ๋‹จ์ˆœ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๊ฐ’์„ ์ฐพ๊ธฐ์œ„ํ•ด ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ˆœํšŒํ•ด์•ผํ•˜๋Š” ๋ฐ˜๋ฉด ํ•ด์‰ฌ ํ…Œ์ด๋ธ”์€ ํ‚ค๋ฅผ ํ†ตํ•ด ๋ฐ”๋กœ ํ•ด์‹œ ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ์ค„์–ด๋“ฆ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋‹ค๋งŒ, ์œ„ ๊ทธ๋ฆผ์—์„œ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ํ•œ ์ธ๋ฑ์Šค๋กœ ๋…ธ๋“œ๊ฐ€ ๋ชจ๋‘ ๋ชฐ๋ฆฌ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋  ๊ฒฝ์šฐ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์™€ ๋‹ค๋ฅธ ์ ์ด ์—†์œผ๋ฏ€๋กœ ํ•ด์‰ฌํ…Œ์ด๋ธ”์˜ ๊ฒ€์ƒ‰์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ O(n)์ด ๋  ์ˆ˜ ์žˆ๋‹ค.(n์€ node์˜ ๊ฐœ์ˆ˜) ๊ทธ๋ž˜์„œ ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ํ•ด์‹œ ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡๋ณด๋‹ค ์ค‘์š”ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถฉ๋Œ(Hash Table Collisions)

๊ฐ€์žฅ ์ด์ƒ์ ์ธ ํ•ด์‹œํ…Œ์ด๋ธ”์€ ํ•œ ๋ฒ„์ผ“์— ๋”ฑ ํ•œ๊ฐœ์˜ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์ด๋‹ค. ๊ทธ๋Ÿด ๊ฒฝ์šฐ์— ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰์˜ ๊ฒฝ์šฐ ์ธ๋ฑ์Šค๋งŒ ๊ณ„์‚ฐํ•˜๋ฉด ๋ฐ”๋กœ ๊ฐ’์„ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ O(1)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ฆ‰, ํ•œ ๋ฒ„์ผ“์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์ถฉ๋Œ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ์—๋Š” ํฌ๊ฒŒ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ์ฒด์ด๋‹๊ณผ ๊ฐœ๋ฐฉ์ฃผ์†Œ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ์ฒด์ด๋‹์€ ํ•ด๋‹น ์ธ๋ฑ์Šค๋ฅผ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฌถ์–ด์„œ ๊ณ„์† ๋’ค์— ๋ง๋ถ™์ด๋Š” ์‹์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๊ณ  ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ๋œ๋‹ค. ๋‘๋ฒˆ์งธ ๊ฐœ๋ฐฉ์ฃผ์†Œ๋ฐฉ๋ฒ•์€ ์ธ๋ฑ์Šค์— ์ด๋ฏธ ๋‹ค๋ฅธ ๋…ธ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋‹ค๋ฅธ ์ธ๋ฑ์Šค๋ฅผ ํƒ์ƒ‰ํ•ด์„œ ๋นˆ ์ธ๋ฑ์Šค์— ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.(๋” ์ˆจ๊ฒจ์ง„ ๋‚ด์šฉ์ด ๋งŽ๋‹ค. ๋‚˜์ค‘์— ์•Œ์•„๋ณด์ž)

์›ฌ๋งŒํ•œ low๋‹จ์ด ์•„๋‹Œ ์–ธ์–ด๋“ค์€ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š”๋ฐ ์—ฌ๊ธฐ์„œ๋Š” ํŒŒ์ด์ฌ์—์„œ ๋ฌธ์ž์—ด์„ ํ•ด์‰ฌํ•˜๋Š” ํ•จ์ˆ˜๋งŒ ์˜ˆ์‹œ๋กœ ๋ณด์ž.

static long string_hash(PyStringObject *a)
{
    register Py_ssize_t len;
    register unsigned char *p;
    register long x;

    if (a->ob_shash != -1)
        return a->ob_shash;
    len = Py_SIZE(a);
    p = (unsigned char *) a->ob_sval;
    x = *p << 7;
    while (--len >= 0)
        x = (1000003*x) ^ *p++;
    x ^= Py_SIZE(a);
    if (x == -1)
        x = -2;
    a->ob_shash = x;
    return x;
}

๋งค์šฐ ๋ณต์žกํ•œ ๊ณผ์ •์„ ํ†ตํ•ด ์ธ๋ฑ์Šค์˜ ์ค‘๋ณต์„ ์—†์• ๋ ค๊ณ  ํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŒŒ์ด์ฌ์—์„œ ํ•ด์‹œํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•œ set, dict๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์›ฌ๋งŒํ•œ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๋ผ๋ฉด ์‹œ๊ฐ„๋ณต์žก๋„ ๊ฑฑ์ •์„ ํฌ๊ฒŒ ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์ฒด์ด๋‹์„ ํ†ตํ•ด ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ตฌํ˜„ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

์ถ”๊ฐ€๋กœ ์ฒด์ด๋‹ํ•  ๋•Œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ singly linked list๋กœ ๋งŒ๋“ค๊ฑฐ๋‚˜ ํ˜น์€ doubly linked list๋กœ ๋งŒ๋“ค์ˆ˜ ์žˆ๋Š”๋ฐ ๋‘˜์„ ๋ชจ๋‘ ๋งŒ๋“ค์–ด๋ณด๊ณ  ๊ทธ ์ฐจ์ด์ ์„ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

๋„์›€๋ฐ›์€ ์ž๋ฃŒ

medium / @bartobri stackoverflow / Where can I find source or algorithm of Python's hash() function? youtube / (์ž๋ฃŒ๊ตฌ์กฐ) ํ•ด์‹œํ…Œ์ด๋ธ”(๋ฆฌ์ŠคํŠธ, ์ฒด์ด๋‹) C์–ธ์–ด๋กœ ์ฝ”๋”ฉํ•ด์š” - by Gunny

1 . singly linked list๋กœ ๊ตฌํ˜„

์„ ์–ธ๋ถ€

// ์ฒด์ด๋‹์„ singly linked list ๋กœ ํ•œ ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ตฌํ˜„
#include <stdio.h>
#include <stdlib.h> // ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์„ ์œ„ํ•จ

struct bucket* hashTable = NULL; 
int BUCKET_SIZE = 10; // ๋ฒ„์ผ“์˜ ์ด ๊ธธ์ด

ํ•ด์‹œํ…Œ์ด๋ธ”์€ ๋ฒ„์ผ“์„ ํ†ตํ•ด ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์— hashTable์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ bucket ๋ฐฐ์—ด ์ฃผ์†Œ๊ฐ’์„ ์„ ์–ธํ•ด๋‘”๋‹ค. ๋ฒ„์ผ“์˜ ์ด ๊ธธ์ด๋Š” 10์ด ๋œ๋‹ค.

๊ตฌ์กฐ์ฒด์„ ์–ธ

// ๋…ธ๋“œ ๊ตฌ์กฐ์ฒด ์„ ์–ธ
struct node {
    int key; // ํ•ด์‹œ ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋  ํ‚ค
    int value; // key ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ
    struct node* next; // ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” ํฌ์ธํ„ฐ
};
// ๋ฒ„์ผ“ ๊ตฌ์กฐ์ฒด ์„ ์–ธ
struct bucket{
    struct node* head; // ๋ฒ„์ผ“ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” ๋…ธ๋“œ์˜ ํฌ์ธํ„ฐ
    int count; // ๋ฒ„์ผ“์— ๋“ค์–ด์žˆ๋Š” ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜
};

๋…ธ๋“œ์™€ ๋ฒ„์ผ“์˜ ๊ตฌ์กฐ์ฒด๋ฅผ ์„ ์–ธํ•œ๋‹ค. ๋…ธ๋“œ - ๋…ธ๋“œ์—๋Š” key, value๊ฐ€ ์žˆ๊ณ  ์ฒด์ด๋‹์ด ๋˜์—ˆ์„ ๋•Œ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” next ํฌ์ธํ„ฐ๋ฅผ ๋ฉค๋ฒ„๋กœ ๊ฐ–๋Š”๋‹ค. ๋ฒ„์ผ“ - ๋ฒ„์ผ“์—๋Š” ๋ฒ„์ผ“์— ์žˆ๋Š” ์ฒซ๋ฒˆ์งธ ๋…ธ๋“œ์˜ ํฌ์ธํ„ฐ์™€ ํ•ด๋‹น ๋ฒ„์ผ“์— ์žˆ๋Š” ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜์ธ count๋ฅผ ๋ฉค๋ฒ„๋กœ ๊ฐ–๋Š”๋‹ค.

์ด์ œ๋ถ€ํ„ฐ ํ•ด์‹œํ…Œ์ด๋ธ”์—์„œ ํ•„์š”ํ•œ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ํ•„์š”ํ•œ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

createNode -> ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ•จ์ˆ˜ hashFunction -> ํ‚ค๋ฅผ ํ•ด์‰ฌ ์ธ๋ฑ์Šค๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ํ•ด์‰ฌ ํ•จ์ˆ˜ add -> ํ‚ค๋ฅผ ํ•ด์‰ฌ ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜ remove_key -> ํ‚ค๋ฅผ ํ•ด์‰ฌ ํ…Œ์ด๋ธ”์—์„œ ์‚ญ์ œํ•˜๋Š” ํ•จ์ˆ˜ search -> ํ‚ค์˜ ๋ฐ์ดํ„ฐ๊ฐ’์„ ์ฐพ์•„์ฃผ๋Š” ํ•จ์ˆ˜ display -> ํ•ด์‰ฌํ…Œ์ด๋ธ” ์ž์ฒด๋ฅผ ์ถœ๋ ฅํ•ด์„œ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜

createNode

// ํ•ด์‰ฌํ…Œ์ด๋ธ” ์‚ฝ์ž…๋  ๋•Œ ์ƒˆ๋กœ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํ•จ์ˆ˜(์ดˆ๊ธฐํ™”)
struct node* createNode(int key, int value){
    struct node* newNode;
    // ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น
    newNode = (struct node *)malloc(sizeof(struct node));
    // ์‚ฌ์šฉ์ž๊ฐ€ ์ „ํ•ด์ค€ ๊ฐ’์„ ๋Œ€์ž…
    newNode->key = key;
    newNode->value = value;
    newNode->next = NULL; // ์ƒ์„ฑํ•  ๋•Œ๋Š” next๋ฅผ NULL๋กœ ์ดˆ๊ธฐํ™”

    return newNode;
}

์‚ฌ์šฉ์ž๊ฐ€ ๋„˜๊ฒจ์ค€ key, value๋กœ ํ•ด์‰ฌํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ๋…ธ๋“œ ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค.

hashFunction

// ํ•ด์‰ฌํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ. ์—ฌ๊ธฐ์„œ๋Š” ๋‹จ์ˆœํžˆ key๋ฅผ ๋ฒ„์ผ“ ๊ธธ์ด๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€๋กœ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ฆ.
int hashFunction(int key){
    return key%BUCKET_SIZE;
}

์ถฉ๋Œ์„ ํ”ผํ•œ ํ•ด์‰ฌํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š”๊ฒŒ ์ค‘์š”ํ•˜์ง€๋งŒ ๋ณธ ๊ธ€์—์„œ๋Š” ์„ค๋ช…์„ ์œ„ํ•ด ๊ฐ„๋‹จํžˆ key๊ฐ’์„ bucket ๊ธธ์ด์ธ 10์œผ๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€๋ฅผ ์ธ๋ฑ์Šค๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด๋ณด์•˜๋‹ค.

add

// ์ƒˆ๋กœ ํ‚ค ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜
void add(int key, int value){
    // ์–ด๋Š ๋ฒ„์ผ“์— ์ถ”๊ฐ€ํ• ์ง€ ์ธ๋ฑ์Šค๋ฅผ ๊ณ„์‚ฐ
    int hashIndex = hashFunction(key);
    // ์ƒˆ๋กœ ๋…ธ๋“œ ์ƒ์„ฑ
    struct node* newNode = createNode(key, value);
    // ๊ณ„์‚ฐํ•œ ์ธ๋ฑ์Šค์˜ ๋ฒ„์ผ“์— ์•„๋ฌด ๋…ธ๋“œ๋„ ์—†์„ ๊ฒฝ์šฐ
    if (hashTable[hashIndex].count == 0){
        hashTable[hashIndex].count = 1;
        hashTable[hashIndex].head = newNode; // head๋ฅผ ๊ต์ฒด
    }
    // ๋ฒ„์ผ“์— ๋‹ค๋ฅธ ๋…ธ๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ํ•œ์นธ์”ฉ ๋ฐ€๊ณ  ๋‚ด๊ฐ€ ํ—ค๋“œ๊ฐ€ ๋œ๋‹ค(์‹ค์ œ๋กœ๋Š” ํฌ์ธํ„ฐ๋งŒ ๋ฐ”๊ฟ”์คŒ)
    else{
        newNode->next = hashTable[hashIndex].head;
        hashTable[hashIndex].head = newNode;
        hashTable[hashIndex].count++;
    }
}

ํ‚ค๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ ์ฒด์ด๋‹์˜ ์–ด๋Š ๋ถ€๋ถ„์— ์‚ฝ์ž…๋˜์–ด๋„ ์ƒ๊ด€์—†์ง€๋งŒ ๋ณธ ๊ธ€์—์„œ๋Š” ์ถ”๊ฐ€๋œ ํ‚ค๊ฐ€ ํ•ญ์ƒ ๋ฒ„์ผ“์˜ head๊ฐ€ ๋˜๋„๋ก ํ•˜์˜€๋‹ค.

remove_key

// ํ‚ค๋ฅผ ์‚ญ์ œํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
void remove_key(int key){
    int hashIndex = hashFunction(key);
    // ์‚ญ์ œ๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” flag ์„ ์–ธ
    int flag = 0;
    // ํ‚ค๋ฅผ ์ฐพ์•„์ค„ iterator ์„ ์–ธ
    struct node* node;
    struct node* before; // ๋…ธ๋“œ๊ฐ€ ์ง€๋‚˜๊ฐ„ ๋ฐ”๋กœ ์ „ ๋…ธ๋“œ
    // ๋ฒ„์ผ“์˜ head๋ถ€ํ„ฐ ์‹œ์ž‘
    node = hashTable[hashIndex].head;
    // ๋ฒ„์ผ“์„ ์ˆœํšŒํ•˜๋ฉด์„œ key๋ฅผ ์ฐพ๋Š”๋‹ค.
    while (node != NULL) // NULL ์ด ๋‚˜์˜ฌ๋•Œ๊นŒ์ง€ ์ˆœํšŒ
    {
        if (node->key == key){
            // ํฌ์ธํ„ฐ ๋ฐ”๊ฟ”์ฃผ๊ธฐ ๋…ธ๋“œ๊ฐ€ 1 . ํ—ค๋“œ์ธ ๊ฒฝ์šฐ 2 . ํ—ค๋“œ๊ฐ€ ์•„๋‹Œ๊ฒฝ์šฐ
            if (node == hashTable[hashIndex].head){
                hashTable[hashIndex].head = node->next; // ๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์ด์ œ ํ—ค๋“œ
            }
            else{
                before->next = node->next; // ์ „๋…ธ๋“œ๊ฐ€ ์ด์ œ ๋‚ด ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ด
            }
            // ๋‚˜๋จธ์ง€ ์ž‘์—… ์ˆ˜ํ–‰
            hashTable[hashIndex].count--;
            free(node);
            flag = 1;
        }
        before = node; // ๋…ธ๋“œ ๋ฐ”๊ฟ”์ฃผ๊ธฐ ์ „์— ์ €์žฅ
        node = node->next;
    }
    // flag์˜ ๊ฐ’์— ๋”ฐ๋ผ ์ถœ๋ ฅ ๋‹ค๋ฅด๊ฒŒ ํ•ด์คŒ
    if (flag == 1){ // ์‚ญ์ œ๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด
        printf("\n [ %d ] ์ด/๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. \n", key);
    }
    else{ // ํ‚ค๊ฐ€ ์—†์–ด์„œ ์‚ญ์ œ๊ฐ€ ์•ˆ๋œ ๊ฒฝ์šฐ
        printf("\n [ %d ] ์ด/๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„ ์‚ญ์ œํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.\n", key);
    }
}

remove ํ•จ์ˆ˜๊ฐ€ doubly linked list๋กœ ์ฒด์ด๋‹์„ ๊ตฌํ˜„ํ•œ ๋ฐฉ์‹๊ณผ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๋ถ€๋ถ„์ด๋‹ค.

๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด A, B, C ๋…ธ๋“œ๊ฐ€ ์ฒด์ด๋‹๋˜์–ด์žˆ์„ ๋•Œ B๋ฅผ ์‚ญ์ œํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด A์˜ next ํฌ์ธํ„ฐ๋ฅผ C๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•œ๋ฐ ์ด๋•Œ B์—์„œ๋Š” A๋กœ doubly linked list์™€ ๋‹ฌ๋ฆฌ ๋ฐ”๋กœ ์ ‘๊ทผํ•  ์ˆ˜๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ•œ๋ฒˆ ๋” search๋ฅผ ํ•ด์ค˜์•ผํ•˜๋Š” ๋ถˆ์ƒ์‚ฌ๊ฐ€ ์ƒ๊ธฐ๋ฏ€๋กœ ์—ฐ์‚ฐ๊ณผ์ •์ด ๋” ๋“ค๊ฒŒ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณธ ๊ธ€ remove_key์—์„œ๋Š” ๋‹ค์Œ ๋…ธ๋“œ๋กœ ๋ฐ˜๋ณต์ž๊ฐ€ ์ด๋™ํ•˜๊ธฐ ์ „์— ๋ฏธ๋ฆฌ before์— ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•ด๋‘ ์œผ๋กœ์„œ ํ•ด๋‹น ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ์—ฐ์‚ฐ๊ณผ์ •์„ ํ”ผํ–ˆ๋‹ค.

search ํ•จ์ˆ˜

// ํ‚ค๋ฅผ ์ฃผ๋ฉด value๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜
void search(int key){
    int hashIndex = hashFunction(key);
    struct node* node = hashTable[hashIndex].head;
    int flag = 0;
    while (node != NULL)
    {
        if (node->key == key){
            flag = 1;
            break;
        }
        node = node->next;
    }
    if (flag == 1){ // ํ‚ค๋ฅผ ์ฐพ์•˜๋‹ค๋ฉด
        printf("\n ํ‚ค๋Š” [ %d ], ๊ฐ’์€ [ %d ] ์ž…๋‹ˆ๋‹ค. \n", node->key, node->value);
    }
    else{
        printf("\n ์กด์žฌํ•˜์ง€ ์•Š์€ ํ‚ค๋Š” ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. \n");
    }
}

ํ•ด๋‹น value๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€์•Š๊ณ  ์ถœ๋ ฅํ•˜๋Š” ์‹์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

display ํ•จ์ˆ˜

// ํ•ด์‹œํ…Œ์ด๋ธ” ์ „์ฒด๋ฅผ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
void display(){
    // ๋ฐ˜๋ณต์ž ์„ ์–ธ
    struct node* iterator;
    printf("\n========= display start ========= \n");
    for (int i = 0; i<BUCKET_SIZE; i++){
        iterator = hashTable[i].head;
        printf("Bucket[%d] : ", i);
        while (iterator != NULL)
        {
            printf("(key : %d, val : %d)  -> ", iterator->key, iterator->value);
            iterator = iterator->next;
        }
        printf("\n");
    }
    printf("\n========= display complete ========= \n");
}

ํ•ด์‹œํ…Œ์ด๋ธ” ๋ฒ„ํ‚ท ์ „์ฒด๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค.

main ํ•จ์ˆ˜

int main(){
    // ํ•ด์‹œํ…Œ์ด๋ธ” ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น
    hashTable = (struct bucket *)malloc(BUCKET_SIZE * sizeof(struct bucket));
}

์ด์ œ ํ•ด์‹œํ…Œ์ด๋ธ”์— ์ง์ ‘ ๊ฐ’์„ ๋„ฃ๊ณ  ๋นผ๋ฉฐ ํ„ฐ๋ฏธ๋„์— ์ถœ๋ ฅํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ณด์ž

iterm2์—์„œ gcc๋กœ ์ปดํŒŒ์ผ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ถœ๋ ฅํ•˜์˜€๋‹ค.

์ปดํŒŒ์ผ

-o [name] ์†์„ฑ์„ ๋ถ™์—ฌ์„œ single์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์‹คํ–‰ํŒŒ์ผ์„ ๋งŒ๋“ค์—ˆ๋‹ค.

์ถœ๋ ฅ ์‹คํ–‰

๋จผ์ € ๊ฐ’ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๋„ฃ๊ณ  ์ถœ๋ ฅํ•ด๋ณด์ž

    // 15 ๊นŒ์ง€ ๊ฐ’ ์ถ”๊ฐ€
    for (int i=0; i < 16; i++){
        add(i, 10*i);
    }
    // ๋ช‡๊ฐœ ๋” ์ถ”๊ฐ€
    add(21, 210);
    add(31, 310);
    add(41, 410);

    display();

๊ฐ’ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์‚ญ์ œํ•ด๋ณด๊ณ  ์ถœ๋ ฅํ•ด๋ณด์ž

    remove_key(31);
    remove_key(11);
    remove_key(51);

    display();

search ํ•จ์ˆ˜๋„ ์‚ฌ์šฉํ•ด๋ณด์ž

    search(11);
    search(1);

2 . doubly linked list๋กœ ๊ตฌํ˜„

์œ„์—์„œ ๊ตฌํ˜„ํ•œ ๋‚ด์šฉ๊ณผ ๊ฑฐ์˜ ๋™์ผํ•˜๋‹ˆ ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๊ณณ๋งŒ ๊ธ€๋กœ ์˜ฎ๊ธฐ๋„๋ก ํ•˜๊ฒ ๋‹ค.

๋…ธ๋“œ ๊ตฌ์กฐ์ฒด

// ๋…ธ๋“œ ๊ตฌ์กฐ์ฒด ์„ ์–ธ
struct node {
    int key; // ํ•ด์‹œ ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋  ํ‚ค
    int value; // key ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ
    struct node* next; // ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” ํฌ์ธํ„ฐ
    struct node* previous; // ์ด์ „ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” ํฌ์ธํ„ฐ
};

์ƒˆ๋กญ๊ฒŒ previous๋ผ๋Š” ํฌ์ธํ„ฐ๊ฐ€ ์ƒ๊ฒผ๋‹ค. ๋‹น์—ฐํžˆ createNode์—์„œ previous ํฌ์ธํ„ฐ๋„ NULL๋กœ ์ดˆ๊ธฐํ™” ํ•ด์ค€๋‹ค. ์ด ํ•จ์ˆ˜ ๋ถ€๋ถ„์€ ์ƒ๋žตํ•œ๋‹ค.

add ํ•จ์ˆ˜

    // ๋ฒ„์ผ“์— ๋‹ค๋ฅธ ๋…ธ๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ํ•œ์นธ์”ฉ ๋ฐ€๊ณ  ๋‚ด๊ฐ€ ํ—ค๋“œ๊ฐ€ ๋œ๋‹ค(์‹ค์ œ๋กœ๋Š” ํฌ์ธํ„ฐ๋งŒ ๋ฐ”๊ฟ”์คŒ)
    else{
        hashTable[hashIndex].head->previous = newNode; // ์ถ”๊ฐ€
        newNode->next = hashTable[hashIndex].head;
        hashTable[hashIndex].head = newNode;
        hashTable[hashIndex].count++;
    }

add ํ•จ์ˆ˜์—์„œ else๋ถ€๋ถ„์— ํ•œ์ค„์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค. ํ•œ์นธ ๋’ค๋กœ ๋ฐ€๋ ค๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กญ๊ฒŒ ๋“ค์–ด์˜จ node๊ฐ€ ์›๋ž˜ ์žˆ๋˜ head์˜ previous๊ฐ€ ๋œ๋‹ค.

remove_keyํ•จ์ˆ˜

// ํ‚ค๋ฅผ ์‚ญ์ œํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
void remove_key(int key){
    int hashIndex = hashFunction(key);
    // ์‚ญ์ œ๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” flag ์„ ์–ธ
    int flag = 0;
    // ํ‚ค๋ฅผ ์ฐพ์•„์ค„ iterator ์„ ์–ธ
    struct node* node;
    // struct node* before; // ํ•„์š” ์—†์Œ!
    // ๋ฒ„์ผ“์˜ head๋ถ€ํ„ฐ ์‹œ์ž‘
    node = hashTable[hashIndex].head;
    // ๋ฒ„์ผ“์„ ์ˆœํšŒํ•˜๋ฉด์„œ key๋ฅผ ์ฐพ๋Š”๋‹ค.
    while (node != NULL) // NULL ์ด ๋‚˜์˜ฌ๋•Œ๊นŒ์ง€ ์ˆœํšŒ
    {
        if (node->key == key){
            // ํฌ์ธํ„ฐ ๋ฐ”๊ฟ”์ฃผ๊ธฐ ๋…ธ๋“œ๊ฐ€ 1 . ํ—ค๋“œ์ธ ๊ฒฝ์šฐ 2 . ํ—ค๋“œ๊ฐ€ ์•„๋‹Œ๊ฒฝ์šฐ
            if (node == hashTable[hashIndex].head){
                node->next->previous = NULL; // ์ถ”๊ฐ€ ์ด์ œ ๋‹ค์Œ๊ป˜ ํ—ค๋“œ๊ฐ€ ๋˜์—ˆ์œผ๋ฏ€๋กœ previous๊ฐ€ ์—†์Œ
                hashTable[hashIndex].head = node->next; // ๋‹ค์Œ ๋…ธ๋“œ๊ฐ€ ์ด์ œ ํ—ค๋“œ
            }
            else{
                node->previous->next = node->next; // ๋‚ด ์ „ ๋…ธ๋“œ์˜ ์•ž์ด ์ด์ œ ๋‚ด ์•ž ๋…ธ๋“œ
                node->next->previous = node->previous; // ๋‚ด ์•ž ๋…ธ๋“œ์˜ ์ „์ด ์ด์ œ ๋‚ด ์ „ ๋…ธ๋“œ
            }
            // ๋‚˜๋จธ์ง€ ์ž‘์—… ์ˆ˜ํ–‰
            hashTable[hashIndex].count--;
            free(node);
            flag = 1;
        }
        node = node->next;
    }
    // flag์˜ ๊ฐ’์— ๋”ฐ๋ผ ์ถœ๋ ฅ ๋‹ค๋ฅด๊ฒŒ ํ•ด์คŒ
    if (flag == 1){ // ์‚ญ์ œ๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด
        printf("\n [ %d ] ์ด/๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. \n", key);
    }
    else{ // ํ‚ค๊ฐ€ ์—†์–ด์„œ ์‚ญ์ œ๊ฐ€ ์•ˆ๋œ ๊ฒฝ์šฐ
        printf("\n [ %d ] ์ด/๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„ ์‚ญ์ œํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.\n", key);
    }
}

์ผ๋‹จ ์ง€๋‚˜์˜จ ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•˜๋˜ before๋Š” ํ•„์š”๊ฐ€ ์—†๊ฒŒ๋˜์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํฌ์ธํ„ฐ๋ฅผ ๋ฐ”๊ฟ”์ค„ ๋•Œ previous๋กœ ๋ฐ”๋กœ ์ ‘๊ทผํ•˜์—ฌ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ •๋˜์—ˆ๋‹ค.

๋‚˜๋จธ์ง€๋Š” ๋™์ผํ•˜๋‹ค.

์ถœ๋ ฅ๋„ ๋™์ผํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. doubly linked list์—๋Š” -> ํ™”์‚ดํ‘œ๊ฐ€ ์•„๋‹Œ <-> ํ™”์‚ดํ‘œ๋ฅผ ์ถœ๋ ฅํ•ด ์ฐจ๋ณ„์ ์„ ๋‘์—ˆ๋‹ค :)

์‹ค์ œ๋กœ ๊ตฌํ˜„๊นŒ์ง€ ํ•ด๋ณด๋‹ˆ ์‚ฌ์šฉํ–ˆ์„ ์  ์ผ์–ด๋‚ฌ๋˜ ์ผ๋“ค์ด ๋”์šฑ ์ดํ•ด๊ฐ€ ์ž˜ ๋œ๋‹ค. ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋Š” ์•„๋ž˜ ๊นƒํ—™์— ๋‚จ๊ธด๋‹ค. ์ด ๊ธ€์„ ๋ˆ„๊ตฐ๊ฐ€ ๋ณธ๋‹ค๋ฉด ์–ด๋ ต์ง€ ์•Š์œผ๋‹ˆ ๊ผญ ํ•œ๋ฒˆ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธธ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜†

github ๋งํฌ