La operación básica y la aplicación del menú de la tabla hash (tabla hash) de la estructura de datos (implementación del programa C)

// El libro de referencia es la estructura de datos y el análisis de algoritmos de Machinery Industry Press (descripción en lenguaje C);

// Este programa es un programa de portabilidad, que utiliza una tabla hash implementada por el método de enlace separado;

// Controle la interfaz de impresión para que tenga un buen efecto de visualización;

// Puede compilar y ejecutar bajo Linux / Mac os / Windows;

// Si tiene alguna deficiencia, por favor menciónela, y el bloguero hará todo lo posible para modificarla;

// Si le resulta útil, por favor, recopile o comparta con otros;

// El plagio y la reimpresión sin permiso están estrictamente prohibidos;

// El código fuente está aquí, espero inspirarte;

// ------------------------------------------------ ----------------------------
//main.c

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "hashtable.h"

int get_first(void);                //获取用户输入的第1个字符;
elemtype input(void);               //处理错误输入;
void eatline(void);                 //清空输入缓冲区;
int show_menu(void);                //提供散列表菜单选项;
void choice(int ch, hashtable *ht); //实现具体操作的函数;

int main(void)
{
    
    
    int ch;
    hashtable *table = initialize_table(TABLESIZE);

    while ((ch = show_menu()) != 'q')
    {
    
    
        choice(ch, table);
    }
    destroy_table(table);
    puts("欢迎下次使用!");

    return 0;
}

int get_first(void)
{
    
    
    int ch;

    do
    {
    
    
        ch = tolower(getchar());
    } while (isspace(ch));
    eatline();

    return ch;
}

elemtype input(void)
{
    
    
    elemtype val;

    printf("请输入一个元素值: ");
    while (scanf("%d", &val) != 1)
    {
    
    
        eatline();
        printf("输入有误!请重新输入: ");
    }
    eatline();
    return val;
}

void eatline(void)
{
    
    
    while (getchar() != '\n')
        continue;
    return;
}

int show_menu(void)
{
    
    
    int ch;

    puts("===============================");
    puts("   欢迎使用散列表菜单");
    puts("a) 为散列表添加新元素");
    puts("b) 删除散列表中的元素");
    puts("c) 在散列表中查找元素");
    puts("d) 遍历打印当前散列表");
    puts("q) 退出本程序");
    puts("===============================");
    printf("请您输入选择: ");
    while (ch = get_first(), strchr("abcdq", ch) == NULL)
    {
    
    
        printf("您的选择无效!请重新输入:");
    }
    return ch;
}

void choice(int ch, hashtable *ht)
{
    
    
    elemtype val;
    pnode pos = NULL;

    switch (ch)
    {
    
    
    case 'a':
    {
    
    
        val = input();
        insert(val, ht);
        break;
    }
    case 'b':
    {
    
    
        val = input();
        cancel(val, ht);
        break;
    }
    case 'c':
    {
    
    
        val = input();
        pos = find(val, ht);
        if (pos != NULL)
        {
    
    
            printf("散列表中存在元素%d\n", val);
        }
        else
        {
    
    
            printf("散列表中不存在元素%d\n", val);
        }
        break;
    }
    case 'd':
    {
    
    
        printf("散列表如下:\n");
        traverse(ht);
        break;
    }
    }
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    return;
}

//hashtable.h

#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#define TABLESIZE 11 //散列表的长度;

typedef int elemtype;
typedef unsigned int index;

typedef struct node
{
    
    
    elemtype data;
    struct node *next;
} list;
typedef struct node *pnode;

typedef struct
{
    
    
    list *table;
    int tablesize;
} hashtable; //散列表(使用链表实现);

//1) 散列函数(除留余数法);
index hash(elemtype key, int size);
/*----------------------------------------------------------------------*/

//2) 初始化大小为size的散列表;
hashtable *initialize_table(int size);
/*----------------------------------------------------------------------*/

//3) 查找散列表中是否存在元素key;
pnode find(elemtype key, hashtable *ht);
/*----------------------------------------------------------------------*/

//4) 为散列表添加元素key;
void insert(elemtype key, hashtable *ht);
/*----------------------------------------------------------------------*/

//5) 从散列表中删除元素key;
void cancel(elemtype key, hashtable *ht);
/*----------------------------------------------------------------------*/

//6) 释放散列表的存储空间;
void destroy_table(hashtable *ht);
/*----------------------------------------------------------------------*/

//7) 遍历散列表;
void traverse(hashtable *ht);
/*----------------------------------------------------------------------*/

#endif

//hashtable.c

#include <stdio.h>
#include <stdlib.h>
#include "hashtable.h"

index hash(elemtype key, int size)
{
    
    
    return key % size;
}

hashtable *initialize_table(int size)
{
    
    
    int i;
    hashtable *new_table = NULL;

    if ((new_table = (hashtable *)malloc(sizeof(hashtable))) != NULL) //分配一个散列表空间;
    {
    
    
        new_table->tablesize = size;
        if ((new_table->table = (list *)malloc(sizeof(list) * size)) != NULL) //为散列表中的链表分配空间;
        {
    
    
            for (i = 0; i < size; i++)
            {
    
    
                new_table->table[i].next = NULL;
            }
        }
        else
        {
    
    
            free(new_table);
            fprintf(stderr, "动态内存分配失败!自动退出本程序!\n");
            exit(EXIT_FAILURE);
        }
    }
    else
    {
    
    
        fprintf(stderr, "动态内存分配失败!自动退出本程序!\n");
        exit(EXIT_FAILURE);
    }
    return new_table;
}

pnode find(elemtype key, hashtable *ht)
{
    
    
    pnode pos = NULL;
    list *templist = &ht->table[hash(key, ht->tablesize)]; //查找元素key所在的位置链表;

    pos = templist->next;
    while (pos != NULL && pos->data != key)
    {
    
    
        pos = pos->next;
    }
    return pos;
}

void insert(elemtype key, hashtable *ht)
{
    
    
    pnode pos = NULL;
    pnode new_node = NULL;
    list *templist = NULL;

    pos = find(key, ht);
    if (NULL == pos)
    {
    
    
        if ((new_node = (pnode)malloc(sizeof(list))) != NULL)
        {
    
    
            templist = &ht->table[hash(key, ht->tablesize)];
            new_node->data = key;
            new_node->next = templist->next;
            templist->next = new_node;
            printf("为散列表添加元素%d成功!\n", key);
        }
        else
        {
    
    
            fprintf(stderr, "动态内存分配失败!自动退出本程序!\n");
            exit(EXIT_FAILURE);
        }
    }
    else
    {
    
    
        printf("散列表中存在元素%d, 无法重复添加!\n", key);
    }
    return;
}

static pnode find_prior(elemtype key, hashtable *ht)
{
    
    
    pnode pos = NULL;
    pnode temp = NULL;
    list *templist = &ht->table[hash(key, ht->tablesize)]; //查找元素key所在的位置链表;

    temp = templist;
    pos = templist->next;
    while (pos != NULL && pos->data != key)
    {
    
    
        temp = pos;
        pos = pos->next;
    }
    return temp; //返回待删除结点的前驱结点地址;
}

void cancel(elemtype key, hashtable *ht)
{
    
    
    pnode pos = NULL;
    pnode temp = NULL;

    pos = find_prior(key, ht); //带删除元素的前驱结点位置;
    temp = pos->next;          //待删除元素的位置;
    if (temp != NULL)
    {
    
    
        pos->next = temp->next;
        free(temp);
        printf("成功删除散列表中元素%d\n", key);
    }
    else
    {
    
    
        printf("散列表中不存在元素%d, 无法删除!\n", key);
    }
    return;
}

void destroy_table(hashtable *ht)
{
    
    
    int i;
    pnode pos = NULL;
    list *templist = NULL;

    for (i = 0; i < ht->tablesize; i++) //释放散列表中各个链表的空间;
    {
    
    
        templist = ht->table[i].next;
        while (templist != NULL)
        {
    
    
            pos = templist;
            templist = templist->next;
            free(pos);
        }
    }
    free(ht); //释放散列表空间;
    return;
}

void traverse(hashtable *ht)
{
    
    
    int i;
    list *templist = NULL;

    for (i = 0; i < ht->tablesize; i++)
    {
    
    
        printf("%2d: ", i);
        templist = ht->table[i].next;
        while (templist != NULL)
        {
    
    
            printf("%d", templist->data);
            if (templist->next != NULL) //控制打印格式;
            {
    
    
                printf(" -> ");
            }
            templist = templist->next;
        }
        putchar('\n');
    }
    return;
}

// ------------------------------------------------ ----------------------------

// ---------------------------- 25 de enero de 2021 -------------- - ---------------

Supongo que te gusta

Origin blog.csdn.net/m0_46181359/article/details/113114738
Recomendado
Clasificación