数据结构 - 哈希表


使用场景

空间换时间,记录一些数据根据映射结果取

C 实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 链表解决冲突
typedef struct Node {
    char *str;
    struct Node *next;
} Node;

typedef struct HashTable {
    Node **data;
    int size;
} HashTable;

// 尾插法
Node *init_node(char *str, Node *head) {
	Node *p = (Node *p) malloc(sizeof(Node));
	p->str = strdup(str);
	p->next = head;
	return p;
}

HashTable *init_hashtable(int n) {
	HashTable *h = (HashTable *) malloc(sizeof(HashTable));
	h->size = n * 2;
	h->data = (Node **) malloc(sizeof(Node *));
	return h;
}

int BKDRHash(char *str) {
	int seed = 31, hash = 0;
	for (int i = 0; str[i]; ++i) hash = hash * seed + str[i];
	return hash & 0x7fffffff; // 符号位置 
}

int insert(HashTable *h, char *str) {
	int hash = BKDRHash(str);
	int ind = hash % h->size;
	h->data[ind] = init_node(str, h->data[ind]);
	return 1;
}

int search(HashTable *h, char *str) {
	int hash = BKDRHash(str);
	int ind = hash % h->size;
	Node *p = h->data[ind];
	while (p && strcmp(p->str, str)) p = p->next;
	return p;
}

void clear_node(Node *node) {
	if (node == NULL) return;
	Node *p = node, *q;
	while (p) {
		q = p->next;
		free(p->str);
		free(p);
		p = q;
	}
	return;
}

void clear_hashtable(HashTable *h) {
	if (h == NULL) return;
	for (int i = 0; i < h->size; ++i) {
		clear_node(h->data[i]);
	}
	free(h->data);
	free(h);
	return;
}

int main() {
	// 模拟
    int op;
    #define max_n 100
    char str[max_n + 5] = {0};
    HashTable *h = init_hashtable(max_n + 5);
    while (~scanf("%d%s", &op, str)) {
        switch(op) {
            case 0:
                printf("insert %s to HashTable\n", str);
                insert(h, str);
                break;
            case 1:
                printf("search %s from HashTable result = %d\n", str, search(h, str));
                break;
        }
    }
    #undef max_n
    clear_hashtable(h);
    return 0;
}

C++ 实现

#include <bits/stdc++.h>

using namespace std;

class HashTable {
private:
    string *elem;
    int size;
public:
    HashTable() {
        size = 2000;
        elem = new string[size];
        for (int i = 0; i < size; i++) {
            elem[i] = "#";
        }
    }
    ~HashTable() {
        delete[] elem;
    }
    int hash(string &value) {
        int code = 0;
        for (size_t i = 0; i < value.length(); i++) {
            code = (code * 256 + value[i] + 128) % size;
        }
        return code;
    }
    bool search(string &value, int &pos, int &times) {
        pos = hash(value);
        times = 0;
        while (elem[pos] != "#" && elem[pos] != value) {
            times++;
            if (times < size) {
                pos = (pos + 1) % size;
            } else {
                return false;
            }
        }
        if (elem[pos] == value) {
            return true;
        } else {
            return false;
        }
    }
    int insert(string &value) {
        int pos, times;
		// 成功找到
        if (search(value, pos, times)) {
            return 2;
        } else if (times < size / 2) { // 冲突,但数据少,开放地址法插入
            elem[pos] = value;
            return 1;
        } else {
        	// 数据多,聚集可能大,重建
            recreate();
            insert(value);
            return 0;
        }
    }
    void recreate() {
        string *temp_elem;
        temp_elem = new string[size];
        for (int i = 0; i < size; ++i) {
            temp_elem[i] = elem[i];
        }
        int copy_size = size;
        size = size * 2;
        delete[] elem;
        elem = new string[size];
        for (int i = 0; i < size; ++i) {
            elem[i] ="#";
        }
        for (int i = 0; i < copy_size; ++i) {
            if (temp_elem[i] != "#") {
                insert(temp_elem[i]);
            }
        }
        delete[] temp_elem;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值