📜  直接地址表(1)

📅  最后修改于: 2023-12-03 15:40:59.521000             🧑  作者: Mango

直接地址表介绍

直接地址表是一种数据结构,常用于表示简单的符号表。它基于散列表原理,通过将符号的键直接映射到哈希表中的槽位,从而实现快速的符号查找和插入操作。在直接地址表中,每个符号的键都被用作哈希表的索引,对应的数据项存储在相应的槽位中,因此,查找操作的时间复杂度为O(1)。

基本实现

直接地址表以一个数组作为哈希表实现,数组中的每个元素都是指向存储该元素对应数据项的指针。在插入符号时,直接通过符号的键计算哈希函数得到槽位索引,将该符号存储在对应的槽位上。

以下是一个简单的直接地址表实现示例:

#define MAX_KEY_LENGTH 32
#define MAX_VALUE_LENGTH 255

struct Symbol {
    char key[MAX_KEY_LENGTH];
    char value[MAX_VALUE_LENGTH];
};

int hash_function(char* key) {
    int hash = 0;
    for (int i = 0; key[i] != '\0'; i++) {
        hash += key[i];
    }
    return hash;
}

void insert(Symbol* table[], Symbol* symbol) {
    int index = hash_function(symbol->key);
    table[index] = symbol;
}

Symbol* lookup(Symbol* table[], char* key) {
    int index = hash_function(key);
    return table[index];
}

void delete(Symbol* table[], Symbol* symbol) {
    int index = hash_function(symbol->key);
    table[index] = NULL;
}
碰撞问题

直接地址表的主要问题是碰撞,当两个不同的符号映射到了同一个槽位时,就发生了碰撞。一种常见的处理碰撞的方法是开放地址法,该方法将所有数据项存储在哈希表中,通过探测序列(例如,线性探测)在哈希表中查找空槽位。

开放地址法的实现可以参考以下代码:

#define MAX_KEY_LENGTH 32
#define MAX_VALUE_LENGTH 255

struct Symbol {
    char key[MAX_KEY_LENGTH];
    char value[MAX_VALUE_LENGTH];
};

enum SlotStatus {
    EMPTY,
    OCCUPIED,
    DELETED
};

struct Slot {
    Symbol* symbol;
    SlotStatus status;
};

int hash_function(char* key) {
    int hash = 0;
    for (int i = 0; key[i] != '\0'; i++) {
        hash += key[i];
    }
    return hash;
}

int probe_sequence(int index, int i) {
    return i;
}

void insert(Slot table[], Symbol* symbol) {
    int index = hash_function(symbol->key);
    int i = 0;
    while (table[index].status == OCCUPIED) {
        i++;
        index += probe_sequence(index, i);
        index %= TABLE_SIZE;
    }
    table[index].symbol = symbol;
    table[index].status = OCCUPIED;
}

Symbol* lookup(Slot table[], char* key) {
    int index = hash_function(key);
    int i = 0;
    while (table[index].status != EMPTY) {
        if (table[index].status == OCCUPIED && strcmp(table[index].symbol->key, key) == 0) {
            return table[index].symbol;
        }
        i++;
        index += probe_sequence(index, i);
        index %= TABLE_SIZE;
    }
    return NULL;
}

void delete(Slot table[], Symbol* symbol) {
    int index = hash_function(symbol->key);
    int i = 0;
    while (table[index].status != EMPTY) {
        if (table[index].status == OCCUPIED && table[index].symbol == symbol) {
            table[index].status = DELETED;
            return;
        }
        i++;
        index += probe_sequence(index, i);
        index %= TABLE_SIZE;
    }
}
总结

以上便是直接地址表的基本实现和碰撞处理方法。直接地址表是一个简单而高效的数据结构,因此在各种应用中有广泛的应用。但是,在使用时需要注意碰撞问题,并选择相应的碰撞处理方法。