数据结构与算法分析-分离链接散列表的实现

简介: #include #include typedef char* ElementType; typedef unsigned int Index; #define MinTableSize 15 struct ListNode; typedef struct ListNode ...
#include<stdio.h>
#include<math.h>

typedef char* ElementType;
typedef unsigned int Index;
#define MinTableSize 15

struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef struct HashTbl *HashTable;

HashTable InitializeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType key,HashTable H);
void Insert(ElementType key,HashTable H);
ElementType Retrieve(Position P);
void Delete(ElementType key,HashTable H);

struct ListNode
{
    ElementType Element;
    Position next;
};

typedef Position List;

struct HashTbl
{
    int TableSize;
    List *TheLists;
};

Index Hash(const char *key,int TableSize)
{
    unsigned int HashVal=0;
    while(*key!='\0')
    {
        HashVal+=*key++;
    }
    return HashVal%TableSize;
}

int NextPrime(int TableSize)
{
    int i,j=2;
    for(i=TableSize;i>0;i--)
    {
        while(j<sqrt(i))
        {
            if(i%j==0)
                break;
            j++;
        }
        if(j==sqrt(i))
            break;
    }
    return i;
}

HashTable InitializeTable(int TableSize)
{
    HashTable H;
    int i;
    if(TableSize<MinTableSize)
    {
        Error("Table size too small");
        return NULL;
    }
    H=malloc(sizeof(struct HashTbl));
    if(H==NULL)
    {
        FatalError("Out of space!!");
    }
    H->TableSize=NextPrime(TableSize);
    H->TheLists=malloc(sizeof(List)*H->TableSize);
    if(H->TheLists==NULL)
    {
        FatalError("Out of space!!");
    }
    for(i=0;i<H->TableSize;i++)
    {
        //分配头节点
        H->TheLists[i]=malloc(sizeof(struct ListNode));
        if(H->TheLists[i]==NULL)
            FatalError("Out of space!!");
        else
            H->TheLists[i]->next=NULL;
    }
    return H;
}

void DestroyTable(HashTable H)
{
    int i;
    for(i=0;i<H->TableSize;i++)
    {
        free(H->TheLists[i]);
    }
    free(H->TheLists);
    free(H);
}

Position Find(ElementType key,HashTable H)
{
    Position P;
    List L;
    L=H->TheLists[Hash(key,H->TableSize)];
    P=L->next;
    while(P!=NULL&&P->Element!=key)
        P=P->next;
    return P;
}

void Insert(ElementType key,HashTable H)
{
    Position Pos,NewCell;
    List L;
    Pos=Find(key,H);
    if(Pos==NULL)
    {
        NewCell=malloc(sizeof(struct ListNode));
        if(NewCell==NULL)
        {
            FatalError("Out of space!!");
        }
        else
        {
            L=H->TheLists[Hash(key,H->TableSize)];
            NewCell->next=L->next;
            NewCell->Element=key;
            L->next=NewCell;
        }
    }
}

ElementType Retrieve(Position P)
{
    if(P==NULL)
        return NULL;
    else
        return P->Element;
}

void Delete(ElementType key,HashTable H)
{
    Position Pos,Pre;
    List L;
    int i;
    Pos=Find(key,H);
    if(Pos==NULL)
        return;
    else
    {
        L=H->TheLists[Hash(key,H->TableSize)];
        for(Pre=L;pre->next!=NUll;Pre=Pre->next)
        {
            if(Pre->next==Pos)
            {
                free(Pos->Element);
                free(Pos);
                break;
            }
        }
    }
}

 

相关文章
|
C语言
链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)
链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)
176 0
|
算法 Java Serverless
数据结构===散列表
数据结构===散列表
|
人工智能 算法 JavaScript
无界SaaS与AI算力算法,链接裂变万企万商万物互联
本文介绍了一种基于无界SaaS与AI算力算法的商业模式的技术实现方案,涵盖前端、后端、数据库及AI算法等关键部分。通过React.js构建用户界面,Node.js与Express搭建后端服务,MongoDB存储数据,TensorFlow实现AI功能。提供了项目结构、代码示例及部署建议,强调了安全性、可扩展性和性能优化的重要性。
|
存储 算法 NoSQL
数据结构和算法——哈希查找冲突处理方法(开放地址法-线性探测、平方探测、双散列探测、再散列,分离链接法)
数据结构和算法——哈希查找冲突处理方法(开放地址法-线性探测、平方探测、双散列探测、再散列,分离链接法)
1185 1
|
存储 C语言
链接未来:深入理解链表数据结构(一.c语言实现无头单向非循环链表)
在上一篇文章中,我们探索了顺序表这一基础的数据结构,它提供了一种有序存储数据的方法,使得数据的访 问和操作变得更加高效。想要进一步了解,大家可以移步于上一篇文章:探索顺序表:数据结构中的秩序之美 今天,我们将进一步深入,探讨另一个重要的数据结构——链表 链表和顺序表一样,都属于线性表,也用于存储数据,但其内部结构和操作方式有着明显的不同。通过C语言的具体实现,我们将会更加直观地理解它
265 1
链接未来:深入理解链表数据结构(一.c语言实现无头单向非循环链表)
|
存储 算法
数据结构和算法——散列表的性能分析(开放地址法的查找性能、期望探测次数与装填因子的关系、分离链接法的查找性能)
数据结构和算法——散列表的性能分析(开放地址法的查找性能、期望探测次数与装填因子的关系、分离链接法的查找性能)
569 0
|
存储 缓存 索引
【数据结构入门精讲 | 第十四篇】散列表知识点及考研408、企业面试练习(1)
【数据结构入门精讲 | 第十四篇】散列表知识点及考研408、企业面试练习(1)
611 0
|
自然语言处理 数据安全/隐私保护
【数据结构入门精讲 | 第十五篇】散列表知识点及考研408、企业面试练习(2)
【数据结构入门精讲 | 第十五篇】散列表知识点及考研408、企业面试练习(2)
142 0
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
365 59
|
9月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
194 0
栈区的非法访问导致的死循环(x64)