查找
来源:互联网 发布:如何电话联系淘宝客服 编辑:程序博客网 时间:2024/04/30 16:57
查找
顺序查找
逐个扫描包中的元素直至找到相应的元素为止
顺序查找的最坏情况:
对于一个含有n个元素的数组,最坏情况是需要n次数组访问
平均情况:
对于一个含有n个元素的数组中,目标可能在的位置为1~n。如果对每个位置进行一次查找,那么平均查找的次数为(1+n)/2
二分查找
只有在数组有序时才能被使用
假如查找的方法为search(array,first,size,target)
array为被查找的数组
first数组中要查找部分的起始下标。
Size要查找的元素个数
target目标元素
查找时,先用中间元素与目标元素比较,如果找到就返回
如果中间元素比目标元素小。
那么递归调用search在数组后半部分查找
如果中间元素比目标元素大
那么在数组的前半部分查找
但size为0时,返回,表示找不到目标元素。
开型寻址散列
packagech11;
/**
*将某些编号映射到数组上的位置这一通用技术称为散列
*某些编号是一个唯一的标识值,称为关键字
*将关键字映射到数组索引的函数叫做散列函数
*如果两个不同的关键字映射到相同的数组索引这种情况称为冲突
*如果data[hash(key)]的位置已经有对象,那就尝试data[hash(key)+1],
*直至找到空闲位置为止.如果到达数组的尽头则重头开始.直至历遍所有位置.
*这种存储算法称为开型寻址.
*@authordou
*
*@param<T>
*@param<V>
*/
publicclassTable<T,V> {
privateT keys[];
privateV data[];
privateboolean[] hasBeenUsed;
privateintmanyItems;
publicTable(intcapacity) {
if(capacity< 0)
thrownewIllegalArgumentException("Capacityis negative");
keys=(T[])newObject[capacity];
data=(V[])newObject[capacity];
hasBeenUsed= newboolean[capacity];
}
/**
*往表中添加元素
*@paramkey关键字
*@paramelement元素
*@return如果新添加的元素是替换原有的元素,那么返回原有元素。否则返回null
*/
publicV put(T key,V element){
intindex = findIndex(key);
Vanswer;
if(index!=-1){
//关键字已存在
answer=data[index];
data[index]=element;
returnanswer;
}elseif(manyItems< data.length){
//关键字不在表中。
index=hash(key);
while(data[index]!=null)
index= nextIndex(index,hash2(key));
keys[index]=key;
data[index]=element;
hasBeenUsed[index]=true;
manyItems++;
returnnull;
}else{
//表已满,抛出错误
thrownewIllegalStateException("Tableis full.");
}
}
/**
*返回关键字是否在表中
*@paramkey
*@return
*/
publicbooleancontainKey(T key){
returnfindIndex(key)!=-1;
}
publicV get(T key){
intindex = findIndex(key);
if(index==-1)
returnnull;
else
returndata[index];
}
publicV remove (T key){
intindex = findIndex(key);
Vanswer=null;
if(index!=-1){
answer=data[index];
data[index]=null;
keys[index]=null;
manyItems--;
returnanswer;
}returnnull;
}
/**
*除法散列函数
*此外还有中-平方散列函数
*乘法散列函数
*/
privateinthash(T key){
returnMath.abs(key.hashCode())%data.length;
}
/*
*再散列,减少聚类
*/
privateinthash2(T key){
return1+Math.abs(key.hashCode())%(data.length-2);
}
/**
*
*@paramindex
*@return
*/
privateintnextIndex(intindex,intstep){
return(index+step)%data.length;
}
/**
*找出key所在的索引
*@paramkey
*@return
*/
privateintfindIndex(T key){
inti=hash(key);
intcount=0;
while(count<data.length&&hasBeenUsed[i]){
if(key.equals(keys[i]))
returni;
i=nextIndex(i,hash2(key));
count++;
}return-1;
}
/**
*输出b~e范围内的所有孪生素数
*定理:若自然数Q与Q+2不能被不大于根号(Q+2)的任何素数整除,则Q与Q+2是一对素数,称为孪生素数。
*@paramb
*@parame
*/
publicstaticvoidtwin_primes(intb,inte){
if(b<3)b=3;
for(inti=b;i<e-1;i++){
intsqrt=(int)(Math.sqrt(i+2));
//System.out.println(sqrt);
intj;
for(j=sqrt;j>1;j--){
if(i%j==0||(i+2)%j==0)
break;
}
if(j==1)System.out.println(i+" "+(i+2));
}
}
publicstaticvoidmain(String args[]){
Table<String,Integer> t=newTable<String, Integer>(10);
twin_primes(1,10000);
}
}
链式散列
将关键字和元素封装成一个链表类,比如:
classChainedHashNode<T,V>{
Tkey;
Velement;
ChainedHashNode<T,V>link;
….
}
然后将Table类中的属性改为
publicclass ChainedTable<T,V>{
publicChainedHashNode<T,V> table[];
}
相同hash值的关键字将存放在同一链表里面
散列的耗时分析
成功查找时平均检验的表元素个数:
装填因子(a)
a=表中元素个数/表的数组大小
使用线性探测的开型寻址散列
1/2*(1+1/(1-a))
使用再散列的开型寻址散列
-ln(1-a)/a
链式散列
1+a/2
0.5
1.5
1.39
1.25
0.6
1.75
1.53
1.3
0.7
2.17
1.72
1.35
0.8
3
2.01
1.4
0.9
5.5
2.56
1.45
1
1.5
2
2
4
3
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- 查找
- linux字体安装
- memcache和数据库的使用技巧
- SQL语句获得本年日期数据与本月日期数据
- 使用C#获得指定打印机所支持的所有PaperSize及PaperName
- SQL
- 查找
- 佛教创始人 - 释迦牟尼佛
- ASP.NET中页面间传值,以及Gridview中的控件示例
- 请问VB.NET中怎么获取当前打印机的纸张类型
- metadata token的含义
- ZK,真正的企业级RIA,让EXTJs走开
- javascript(1) 脚本片断放置的位置
- 生成多文件的Assembly 的两种方法
- Linux下获得网卡MAC地址,IP地址及子网掩码