Estructura de datos: hash

Una tabla hash es una estructura de datos que utiliza una función hash para organizar datos, lo que admite una inserción y búsqueda rápidas.

Una tabla hash (también conocida como tabla hash) funciona asignando claves a direcciones de depósitos con la ayuda de una función hash. Más precisamente,
1. Primero abra una matriz de depósitos de cierta longitud con direcciones físicas continuas;
2. Cuando insertemos una nueva clave, la función hash decidirá a qué depósito se debe asignar la clave y asignará la clave a Almacenada en el depósito correspondiente
3. Cuando queremos buscar una clave, la tabla hash utilizará la función hash para encontrar el depósito correspondiente y buscar en ese depósito.

El factor de carga, también llamado factor de relleno, es un parámetro importante de la tabla hash, que refleja la plenitud de la tabla hash.
La relación entre el número real de cangilones utilizados y el número total de cangilones se denomina factor de carga.

función hash

La función hash es el componente más importante de una tabla hash y se utiliza para asignar claves a depósitos específicos. Usamos y = x % 5 como función hash, donde x es el valor clave e y es el índice del depósito correspondiente después del mapeo.

la resolución de conflictos

En circunstancias normales, la función hash desempeñará la función de comprimir el espacio de direcciones de la clave. Supongamos que el espacio de direcciones de la clave es S y el espacio de direcciones del depósito es T, entonces S≫T.
Por lo tanto, después del mapeo, inevitablemente se asignarán datos diferentes al mismo depósito y se producirán conflictos.

heurística lineal

El método heurístico lineal es un método de direccionamiento abierto. El llamado método heurístico lineal significa que al insertar la clave, si se encuentra que el cubo de la unidad de cubo [hash (clave)] ya está ocupado, entonces se realiza la búsqueda lineal. se realizará hacia abajo hasta que se encuentre un espacio vacío utilizable. Específicamente, después de la prueba i-ésima, la unidad del depósito debe ser: depósito[(hash(clave)+i) mod M], i=1,2,3…

método de dirección de cadena

Otra forma de resolver conflictos es concatenar las claves en conflicto del depósito en una lista vinculada.

refrito

Una aplicación típica del refrito es el doble hash, es decir, cuando ocurre un conflicto, se utiliza otra función hash para evitar el conflicto.
Sin embargo, el doble hash también tiene algunos problemas:
1. En comparación con la heurística lineal, el doble hash consume más tiempo.
2. En el caso del doble hash, la eliminación complicará el problema. Si el número de eliminaciones lógicas es demasiado grande, se debe reconstruir la tabla hash.

Ley de áreas públicas de derrames

Como sugiere el nombre, el método del área de desbordamiento público es crear otra tabla hash dict_overflow como área de desbordamiento público. Cuando ocurre un conflicto, la clave se guarda en la tabla hash.

conjunto de hash simple

#define MAX_LEN 100000          // 初始化桶的数量

class MyHashSet {
    
    
private:
    vector<int> set[MAX_LEN];   // 使用数组实现哈希集合
    
    /** 返回对应的桶的索引 */
    int getIndex(int key) {
    
    
        return key % MAX_LEN;
    }
    
    /** 在特定的桶中搜索键,如果该键不存在则返回 -1 */
    int getPos(int key, int index) {
    
    
        // 每个桶中包含一个列表,遍历所有桶中的元素来寻找特定的键
        for (int i = 0; i < set[index].size(); ++i) {
    
    
            if (set[index][i] == key) {
    
    
                return i;
            }
        }
        return -1;
    }
public:
    
    MyHashSet() {
    
    
        
    }
    
    void add(int key) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
    
    
            // 如果键不存在,则添加
            set[index].push_back(key);
        }
    }
    
    void remove(int key) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos >= 0) {
    
    
            // 如果键存在,则删除
            set[index].erase(set[index].begin() + pos);
        }
    }
    
    bool contains(int key) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        return pos >= 0;
    }
};

mapa hash simple

#define MAX_LEN 100000            // 初始化桶的数量

class MyHashMap {
    
    
private:
    vector<pair<int, int>> map[MAX_LEN];       // 使用数组实现哈希集合
    
    /** 返回指定桶的索引 */
    int getIndex(int key) {
    
    
        return key % MAX_LEN;
    }
    
    /** 在桶中搜索键,如果不存在则返回 -1 */
    int getPos(int key, int index) {
    
    
        // 每个桶包含一个数组,遍历桶中的所有元素来查找指定的 key
        for (int i = 0; i < map[index].size(); ++i) {
    
    
            if (map[index][i].first == key) {
    
    
                return i;
            }
        }
        return -1;
    }
    
public:
    MyHashMap() {
    
    
        
    }
    
    /** value 始终为正 */
    void put(int key, int value) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
    
    
            map[index].push_back(make_pair(key, value));
        } else {
    
    
            map[index][pos].second = value;
        }
    }
    
    /** 如果存在映射关系,则返回 value,否则返回 -1 */
    int get(int key) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
    
    
            return -1;
        } else {
    
    
            return map[index][pos].second;
        }
    }
    
    /** 如果存在 key 的映射,则删除该映射关系 */
    void remove(int key) {
    
    
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos >= 0) {
    
    
            map[index].erase(map[index].begin() + pos);
        }
    }
};

Supongo que te gusta

Origin blog.csdn.net/weixin_43945471/article/details/132701132
Recomendado
Clasificación