算法导论 直接寻址表
算法导论 第11章 散列表
11.1 直接寻址表
如果某应用要用到一个动态集合,其中每个元素都是全域U={0,1….,m}中的一个关键字
为表示动态集合,使用数组。称为直接寻址表,记为T[m],其中每个位置称为一个槽slot,对应于全域中的一个关键字
槽k指向集合中一个关键字为k的元素。如果该集合中没有关键字为k的元素,则T[k]=NIL;
程序实现思路:
- 可以用静态数组实现,因为数组的下标等于关键字,所以可以用数组存放对应的元素。有几个缺点:首先难以确定NULL,由于数组元素的类型是确定的,所以如何用某个数来表示NULL,表示数组中没有此元素,是一个问题。如果具体问题中,用不上其某个元素,可以使用该元素作为数组的NULL。
- 用指针数组实现,该方法普适程度高,数组中的元素都是指针,指向结构体,该结构体有两个参量,一个是关键字key,一个是卫星数据satellite。如果没有该关键字,则可以为指针赋值NULL,较容易实现。
下面给出指针数组的C语言实现
```
#include<stdio.h>
typedef int Elemtype ; //定义结构体中存储的元素类型 注:若要改变其元素类型,在print_hash()函数中对应的printf函数也要改变define MAX 100 //定义全集大小
typedef struct hash //定义结构体
{int key; //关键字Elemtype satellite; //元素类型
}Hash; //结构体名称为Hash//查找一个给定关键字为key的元素
Elemtype Direct_address_search(Hash* a[],int key)
{if(a[key]==NULL) //判断关键字是否在{printf("the key element is not in list\n");exit(0);}return a[key]->satellite; //返回该关键字对应的数据
} //插入一个元素
void Direct_address_insert(Hash* a[],Hash* x)
{a[x->key]=x;
}//删除一个元素
void Direct_address_delete(Hash* a[],Hash* x)
{a[x->key]=NULL;
}//打印直接寻址表
void print_hash(Hash* a[])
{ int i=0;while(i<MAX){if(a[i]!=NULL){printf("%d %d\n",a[i]->key,a[i]->satellite);}i++; }
}//测试函数
int main()
{Hash* data[MAX];int i;int x;//创建直接寻址表,并初始化为空for(i=0;i<MAX;i++)
{data[i]=(Hash*)malloc(sizeof(Hash));// printf("%d\t",data[i]);data[i]=NULL;// printf("%d\n",data[i]);}//给出元素(5,100),(2,200),(0,300)进行测试Hash* a=(Hash*)malloc(sizeof(Hash));a->key=5;a->satellite=100;Hash* b=(Hash*)malloc(sizeof(Hash));b->key=2;b->satellite=200;Hash* c=(Hash*)malloc(sizeof(Hash));c->key=0;c->satellite=300;Direct_address_insert(data,a);Direct_address_insert(data,b);Direct_address_insert(data,c);x=Direct_address_search(data,5);Direct_address_delete(data,a);print_hash(data);//释放内存for(i=0;i<MAX;i++)free(data[i]);free(a);free(b);free(c);return 0;
}
```
练习11.1-1
查找S中最大的数,需要遍历整个表,所以复杂度为O(n)
下面给出其代码:
```
Elemtype direct_address_Maxsearch(Hash* t[],int m)
{int i;Elemtype max;for(i=0;i<m;i++){if(a[i]!=NULL){ max=a[i]->satellite;break;}}if(i==m){printf("no element in the hast table\n");exit(0);}for(;i<m;i++){if(a[i]!=NULL&&a[i]->satellite>max)max=a[i]->satellite;}return max;
}
```
习题11.1-2 实现位向量
分析:题目中说用位向量来表示一个包含不同元素的动态集合,并且不需要卫星数据,所以就是给定一个集合,判断整型关键字是否在里面,位向量是0和1的数组。为了节省空间,用一个整型的32位来存储32个数,从0-31,并且该数应该是连续的。不连续的存储需要特定的hash函数来映射。对于给定总数大小n,如果要存储其n个数,用位向量来存储只需(n/32+1)个整型量,主要的操作是插入一个数,删除一个数,搜索一个数。
具体代码如下:
```
#include<stdio.h>
#include<stdlib.h>
#define BIT_INT 32
//定义该结构体
typedef struct bit_vector
{unsigned int* table;int size;
} Bitvector;
//初始化
Bitvector* bit_create(int size)
{Bitvector* bit=(Bitvector*)malloc(sizeof(Bitvector));bit->size=size/BIT_INT+1;bit->table=(unsigned int*)calloc(sizeof(int),bit->size);return bit;
}
//插入key
void Bit_insert(Bitvector* bit,int key)
{bit->table[key/BIT_INT]|=(1<<(key%BIT_INT));
}
//删除操作
void Bit_delete(Bitvector* bit,int key)
{bit->table[key/BIT_INT]&=~(1<<(key%BIT_INT));
}//返回值为1说明存在,为0说明不存在
int Bit_search(Bitvector* bit,int key)
{return (bit->table[key/BIT_INT]&(1<<(key%BIT_INT)))!=0;
}//打印元素值
void print_bit(Bitvector* bit)
{int i;int size=bit->size*BIT_INT;for(i=0;i<size;i++)if(Bit_search(bit,i)==1)printf("%d\n",i);printf("\n");
}
//释放内存
void Bit_destory(Bitvector* bit)
{free(bit->table);free(bit);
}int main()
{Bitvector* bit=bit_create(1024);int i,x;Bit_insert(bit,15);Bit_insert(bit,250);Bit_insert(bit,900);print_bit(bit);Bit_delete(bit,250);print_bit(bit);printf("------------------\n");x=Bit_search(bit,2);printf("sousuo : %d\n",x);x=Bit_search(bit,900);printf("sousuo: %d\n",x);Bit_destory(bit);return 0;
}
```
参考来源:
习题11.1-3
分析:该题目可以用链表来解决。对于有相同key值的数,在该key值处用链表链接。
习题11.1-4
想法:
由于大数组太大,不能初始化,我们也就等于不知道到底哪里有真正的数据,于是乎数据不能存储在大数组中,因为你根本不知道到底哪里才是数据。
这里方式是:将数据存储到栈上,栈上的增删查都可以实现O(1),然后在大数组上,对应key的位置的元素,存放栈上对应的下标,这样根据key到大数组中找到栈的下标,然后根据栈的下标又可以找到那个key值对应的数据元素了。
然后,还需要解决如何判断数据是否有效的问题,这个也很简单,经过上面的查找过程,不难发现,如果该数据是有效的,需要满足以下几个条件:
1. key值对应到大数组中位置的值,必须位于[0,栈的栈顶位置]之间,否则肯定不是数据
2. 满足第1条之后,我们到栈上对应的位置,找到那个元素数据,它的key值要反过来等于我们原始的key值,否则表示这个数据也是不存在的.
参考来源
代码如下:
```
#include<stdio.h>
#define MAX 100
#define large_number 10000
int Hash[large_number];struct
{int Stack[MAX];int top;
} stack;void init(stack* s)
{s->top=-1;
}
//search the element k
int search(int* hash,stack* s,int value)
{int num=hash[value];if(num>0&&num<=s->top&&s.Stack[num]==value)return num;return 0;
}void insert(int* hash,stack* s,int x)
{if(search(hash,s,x)!=0){printf("already exist\n");return ;}s->top++;s.Stack[s->top]=value;hash[value]=s->top;
}void delete(int* hash,stack* s,int value)
{int num=search(hash,s,value);if(num){int val=s->Stack[s->top];s->Stack[num]=val;s->top--;hash[val]=num;printf("delete successfully\n");}elseprintf("delete failed\n");
}
```
算法导论 直接寻址表相关推荐
- 假设一动态集合S用一个长度为m的直接寻址表T来表示。请给出一个查找S中最大元素的过程。(算法导论第十一章11.1-1)
假设一动态集合S用一个长度为m的直接寻址表T来表示.请给出一个查找S中最大元素的过程.你所给的过程在最坏情况下的运行时间是多少. (算法导论第十一章11.1-1) #include "Key ...
- MIT算法导论公开课第七讲哈希表
哈希表又称散列表,其定义是根据一个哈希函数将集合S中的关键字映射到一个表中,这个表就称为哈希表,而这种方法就称为Hashing.从作用上来讲,构建哈希表的目的是把搜索的时间复杂度降低到O(1),考虑到 ...
- 【算法导论33】跳跃表(Skip list)原理与java实现
Skip list是一个用于有序元素序列快速搜索的数据结构,由美国计算机科学家William Pugh发明于1989年.它的效率和红黑树以及 AVL 树不相上下,但实现起来比较容易.作者William ...
- 算法设计与分析——散列表/哈希表(Hash Table):直接寻址表
分类目录:<算法设计与分析>总目录 相关文章: ·散列表/哈希表(Hash Table)(一):基础知识 ·散列表/哈希表(Hash Table)(二):直接寻址表 ·散列表/哈希表(Ha ...
- 【MIT算法导论】哈希表、全域哈希
哈希表及哈希算法 一. 直接寻址 1. 应用条件 当关键字的全域比较小时(也即:候选的关键字的数目较少),直接寻址法才是行之有效的. p.s. 借用下图,即U(全域)很小,那么需要存储的部分K(实际需 ...
- 算法导论程序24--直接寻址表(Python)
当关键字的全域U比较小时,直接寻址是一种简单而有效的技术. 假设某应用要用到一个动态集合,其中每个元素都是取自全域U={0,1,... ,m-1}中的一个关键字,这里m不是一个很大的数.另外,假设 ...
- 《算法导论》学习分享——11. 散列表(哈希表)
11. 散列表(哈希表) 文章目录 11. 散列表(哈希表) 直接寻址表 散列表 链接法散列分析 散列函数 除法散列 乘法散列 全域散列 开放寻址法 线性探查 双重探查 开放寻址法分析 完全散列 涉及 ...
- 散列表(算法导论笔记)
散列表 直接寻址表 一个数组T[0..m-1]中的每个位置分别对应全域U中的一个关键字,槽k指向集合中一个关键字为k的元素,如果该集合中没有关键字为k的元素,则T[k] = NIL 全域U={0,1, ...
- 基本数据结构(算法导论)与python
Stack, Queue Stack是后进先出, LIFO, 队列为先进先出, FIFO 在python中两者, 都可以简单的用list实现, 进, 用append() 出, Stack用pop(), ...
最新文章
- 3.实现串口功能及消息邮箱
- gantt markdown
- Python学习(四)
- Thymeleaf提取公共页面(从实例入手,以inspinia模板为例)
- IOS 打包证书签名 shell脚本
- oracle 查看用户状态,Oracle数据库查看用户状态
- 哪些原因会导致rs485转换器信号受干扰?
- 文件系统ext3的文件大小限制
- 消息(5)——WSE增强的web服务套件,MTOM附件
- 单片机基础学-按键篇
- 计算机网络的服务资源管理器,MCSA学习指南-配置文件服务器资源管理器-文件服务器...
- 内向的人和陌生人聊天,如何做到有话可说
- 安全算法-对称加密与非对称加密
- 浅谈老妈的QQ号被盗之后
- 学会这几招,能找到90%以上的资源
- 钉钉 服务器 消息推送,【20210727 更新】 全能推送PushBot(原钉钉推送)支持企业微信,PushPlus,Bark...
- 【MM小贴士】SAP采购订单创建参考采购申请的强控
- 总结一些常见的国际标准化组织
- Spring整合Quartz集群部署
- 网络骗子的特征。大家一定要转载。