简单排序
- 冒泡排序
- 效率和逆序对大小有关
- 插入排序
- 效率和逆序对大小有关
- 希尔排序
散列查找
- 痛点:传统二分查找无法解决查找高效率的同时,可以添加删除。也就是动态查找。所以散列应运而生。
- 查找本质:已知对象找位置
- 有序安排对象[全部有序(二分查找)、部分有序(查找树)]
- 直接“算出”对象位置:散列
- 散列查找两项基本工作
- 计算位置:构造散列函数确定关键词位置
- 解决冲突:应用某种策略解决多个关键词位置相同的问题。
- 时间复杂度几乎是常量:O(1),即查找时间与问题规模无关。
- 散列函数是对17求余数,eq:20/17=3
- 装填因子LoadFactor= 11/17 = 0.65(装入元素个数/散列表大小)
- 基本思想
- 以关键字key为自变量,通过一个确定的函数(散列函数),计算出对应的函数值作为数据对象的存储地址。
- 不同的关键字映射到同一个散列地址上,称为冲突,需要冲突解决策略。
- 散列函数构造(数字)
- 直接定址法,h(key) = a*key+b(ab为常数)
- 除留余数法,求余数 h(key) = key % 17,一般p为表的大小p=tableSize=17,取素数
- 折叠法,如:56793542 -542+793+052=1391 所以,h(56793542)=391
- 平方取中法:如56793542 * 56793542 = 322550641 2905764 所以,h(56793542)=641。取中和折叠都是希望结果被更多位数产生影响
- 散列函数构造(字符)
h(abcde) = a* 324+ b *323+c *322+d 32+e [32进制的五位数] 精简为 ==>(a32+b)*32 +c
结果在求余数
高效算法:(a<<5 +b)<<5+c[乘法次数越少计算机越高效 ]
冲突处理
-
换个位置:开放地址法
-
一旦产生冲突(该位置已有其他元素)就按照某种规则寻找另一个空地址。
-
h1(key)=h(key) + di(0<i<tableSize),di决定了三种探测方案:线性探测法[di=i]、平方探测法[di=i2]、双散列探测法[di=i*h2(key)]
-
线性探测法:冲突容易积聚
-
平方探测法:以增量序列12,-12,22,-22。。。q2,-q2,q<=tableSize/2,循环试探下一个存储地址。
- 好处:避免了聚集,但是坏处是有可能发生即使有空位置仍然找不到的情况。
- 定理:如果哈西表长度tableSize是某个(4K+3)形式的素数,平方探测法就可以探查到整个散列表空间。
-
双散列探测法:di=i*h2(key)。h2(key)是另一个散列函数。探测序列成h2(key);2h2(key);3h2(key)…
-
再散列rehashing;当散列元素太多,装填因子太大,查找效率就会降低。解决办法是加倍扩大散列表,这个过程叫再散列(rehashing)
-
-
同一个位置的冲突对象组织在一起:链地址法(分离链接法)
- 将相同位置上冲突的所有关键词存储在同一个单链表中。