数据结构基础(三)习题未处理

一、链表:

和数组都可以用于存储数据,其中链表通过指针来连接元素,而数组则是把所有元素按照次序存储。

数组和链表有不同的优势:

链表:可以方便地删除插入数据,操作次数为O(1),但寻找读取据的效率低,在随机访问数据中的操作次数为O(n)。

数组:可以方便地寻找读取数据,在随机访问中操作次数为O(1),但删除插入的操作次数为O()

1.单向链表:
包含数据域和指针域。

struct node{
   
	int value;
	node *next;
}

(1)插入元素:
在p与p->next之间插入一个数据x:

x->next=p->next;
p->next=x;

(2)删除元素:
删除节点p的数据:
将p->next的数据覆盖到p上

p->value=p->next->value;
p->next=p->next->next;

2.双向链表:
同样具有数据域和指针域,不同之处在于指针域有左右之分。

struct node{
   
	int val;
	node *left;
	node *right;
}

(1)插入元素:
在p和p->right之间插入元素x:

x->right=p->right;
x->left=p;
p->right->left=x;
p->right=x;

(2)删除元素:
删除节点p:

p->left->right=p->right;
p->right->left=p->left;

【例题】办公楼

有n个职员,有m对职员之间有联系。若两个职员之间有联系,他们就可以被安置在两座办公楼内。问最多能将这n个职员安排在几座办公楼内。

N<=100000,m<=2000000

两个点若没有联系即连边,建立原图的补图。

二、哈希表

又称散列表,一种以"key-value"形式存储数据的数据结构。所谓以"key-value"形式存储数据,是指任意的key都唯一对应到内存中的某个位置,只需要输入查找的值key,就可以快速地找到其对应的value。可以把哈希表理解成一种高级的数组,这种数组的下表可以是很大的整数,浮点数,字符串甚至结构体。

1.哈希函数:

要让key对应到内存中的位置,就要为key计算索引,也就是计算这个数据应该放在哪里,根据key计算索引的函数叫做哈希函数,也称散列函数。哈希函数应当易于计算,且尽量使计算出来的索引均与分布。

2.常见处理方式:

在OI中,最常见的情况应该是key为整数的情况。当key范围较大时,需要用到哈希表,通常取f(x)=x mod M作为哈希函数,M为一个大质数。
另一种比较常见的情况是 key 为字符串的情况,在 OI 中,一般不直接把字符串作为 key,而是先算出字符串的哈希值,再把其哈希值作为 key 插入到哈希表里。

3.冲突:

如果对于任意的key,哈希函数计算出来的索引都不相同,那只用根据索引把 (key,value) 放到对应的位置就行了。但实际上,常常会出现两个不同的 key,他们用哈希函数计算出来的索引是相同的。这时候就需要一些方法来处理冲突。在 OI 中,最常用的方法是拉链法。

4.拉链法:

拉链法也称开散列法。拉链法是在每个存放数据的地方开一个链表,如果有多个 key 索引到同一个地方,只用把他们都放到那个位置的链表里就行了。查询的时候需要把对应位置的链表整个扫一遍,对其中的每个数据比较其 key 与查询的 key 是否一致。如果索引的范围是 1~M,哈希表的大小为 N,那么一次插入/查询需要进行期望O(N/M)次比较。

const int M=999997;
struct hashtable{
   
	struct node{
   
		node *next;
		int key,value;
	};
	node *head[M];
}
int f(int key){
   
	return key%M;
}//哈希函数
int get(int key){
   
	for(node *p=head[f(key)];p;p=p->next){
   
		if
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值