size, ht->cap, ht_prime_mod[ht->modid]); Node *hd = ht->head, *cur = hd->next; while (cur != hd) { "> size, ht->cap, ht_prime_mod[ht->modid]); Node *hd = ht->head, *cur = hd->next; while (cur != hd) { "> size, ht->cap, ht_prime_mod[ht->modid]); Node *hd = ht->head, *cur = hd->next; while (cur != hd) { ">
// ==================== hash table =======================
typedef int HT_KT;
typedef struct {
    int lev;
    int val;
} kt;
// 值类型
typedef kt HT_VT;
const unsigned int ht_prime_mod[] = {13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859};
const unsigned int ht_pow_mod[] = {16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864};
typedef struct Node {
    unsigned int h;
    HT_KT key;
    HT_VT val;
    struct Node* next;
    struct Node* prev;
} Node;

typedef struct {
    Node** table;
    int size;
    int cap;
    int modid;
    Node* head;
} hashtable;

// modfy
void ht_print(hashtable* ht) {
    // your code
    printf("hashtable size:%d, cap:%d, mod:%d", ht->size, ht->cap, ht_prime_mod[ht->modid]);
    Node *hd = ht->head, *cur = hd->next;
    while (cur != hd) {
        if (cur->h != cur->prev->h) {
            printf("\\nbucket hash %d:", cur->h);
        }
        printf(" [key=%d, lev=%d, val=%d]", cur->key, cur->val.lev, cur->val.val); // modify
        cur = cur->next;
    }
    printf("\\n");
}

unsigned int ht_hash(hashtable* ht, HT_KT key) {
    unsigned int mod = ht_prime_mod[ht->modid];
    return (mod+(key^key>>16)%mod)%mod;
}

hashtable* ht_new() {
    hashtable* ht = (hashtable*)malloc(sizeof(hashtable));
    assert(ht != NULL);
    
    int cap = 16;
    ht->table = (Node**)malloc(cap * sizeof(Node*));
    assert(ht->table != NULL);
    memset(ht->table, 0, cap*sizeof(Node*));
    
    ht->head = (Node*)malloc(sizeof(Node));
    assert(ht->head != NULL);
    ht->head->prev = ht->head->next = ht->head;
    ht->head->h = -1;

    ht->size = 0;
    ht->cap = cap;
    ht->modid = 0;

    return ht;
}

void ht_del(hashtable* ht) {
    free(ht->table);
    free(ht->head);
    free(ht);
}

bool ht_has(hashtable* ht, HT_KT key) {
    unsigned int hkey = ht_hash(ht, key);
    Node* hnode = ht->table[hkey];
    if(hnode == NULL) return 0;
    while (hnode->h == hkey) {
        if (hnode->key == key) 
            return 1;
        hnode = hnode->next;
    }
    return 0;
}

void ht_add(hashtable* ht, Node* node) {
    Node *hnode = ht->head;   
    if (ht->table[node->h]) {
        hnode = ht->table[node->h];
    }
    node->prev = hnode->prev;
    node->next = hnode;
    node->prev->next = node;
    node->next->prev = node;
    ht->table[node->h] = node;

    ht->size += 1;
}

void ht_set(hashtable* ht, HT_KT key, HT_VT val) {
    // 检测已经存在key
    unsigned int hkey = ht_hash(ht, key);
    Node* hnode = ht->table[hkey];
    while (hnode != NULL && hnode->h == hkey) {
        if (hnode->key == key) {
            hnode->val = val;
            return ;
        }
        hnode = hnode->next;
    }
    // 不存在
    Node *node = (Node*)malloc(sizeof(Node));
    node->h = hkey;
    node->key = key;
    node->val = val;
    ht_add(ht, node);
    // 达到cap扩容二倍
    if (ht->size > ht->cap) {
        ht->size = 0;
        ht->cap *= 2;
        ht->modid += 1;
        free(ht->table);
        ht->table = (Node**)malloc(ht->cap * sizeof(Node*));
        memset(ht->table, 0, ht->cap*sizeof(Node*));
        // head自成环,链表剩余节点重新插入
        Node *hnode = ht->head, *remain = hnode->next, *nxt;
        hnode->prev->next = NULL;
        hnode->prev = hnode;
        hnode->next = hnode;
        
        while (remain != NULL) {
            nxt = remain->next;
            remain->h = ht_hash(ht, remain->key);
            ht_add(ht, remain);
            remain = nxt;
        }
    }
}

HT_VT ht_get(hashtable* ht, HT_KT key) {
    unsigned int hkey = ht_hash(ht, key);
    Node* hnode = ht->table[hkey];
    assert(hnode != NULL);

    while (hnode->h == hkey) {
        if (hnode->key == key) 
            return hnode->val;
        hnode = hnode->next;
    }
    assert(0);
}

void ht_pop(hashtable* ht, HT_KT key) {
    unsigned int hkey = ht_hash(ht, key);
    Node* hnode = ht->table[hkey];
    assert(hnode != NULL);

    while (hnode->h == hkey) {
        if (hnode->key == key) 
            break;
        hnode = hnode->next;
    }
    assert(hnode->key == key);
    hnode->prev->next = hnode->next;
    hnode->next->prev = hnode->prev;
    if (hnode == ht->table[hkey]) {
        ht->table[hkey] = hnode->next;
        if (ht->table[hkey]->h != hkey)
            ht->table[hkey] = NULL;
    }
    free(hnode);
    ht->size -= 1;
}