算法导论 直接寻址表
来源:互联网 发布:大数据的发展阶段 编辑:程序博客网 时间:2024/06/14 22:47
算法导论 第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;}//插入keyvoid 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 10000int 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"); } else printf("delete failed\n");}```
- 算法导论 直接寻址表
- 算法导论 11.1-4 大数组的直接寻址表
- 《算法导论》笔记 第11章 11.1 直接寻址表
- 算法导论11.1直接寻址表 练习总结
- 算法导论程序24--直接寻址表(Python)
- 算法-----直接寻址表
- 《算法导论》第11章 散列表 (1)直接寻址表
- 算法导论-第11章-散列表-11.1-4 大数组的直接寻址表
- 直接寻址表_第11章_散列表_算法导论
- 算法导论:开放寻址
- 算法导论 开放寻址法
- [数据结构] 直接寻址表
- 【算法导论】十一章散列表11.1-4大数组实现直接寻址方式的字典操作
- CLSR 11.1直接寻址表
- 《算法导论》第11章 散列表 (3)开放寻址
- 《算法导论》笔记 第11章 11.4 开放寻址法
- 算法导论11.4开放寻址法 练习总结
- 算法导论程序26--开放寻址法(Python)
- C语言之实型数据类型
- C++类的使用
- 最短路径之Floyd-Warshall
- 全网股票爬取
- MySQL分区表的局限和限制
- 算法导论 直接寻址表
- 给出一个不多于5位的整数,要求 1、求出它是几位数 2、分别输出每一位数字 3、按逆序输出各位数字,例如原数为321,应输出123
- Linux 搭建安卓后台开发环境--------Tomcat 和 NetBeans
- Hook技术之View点击劫持
- 算法作业_8(2017.3.19第四周)
- iframe局部刷新技术的<<<STR
- 操作系统——用户界面
- 超经典的题目——学生管理系统(Android版)
- Android开发中的工具插件