查找

来源:互联网 发布:如何电话联系淘宝客服 编辑:程序博客网 时间:2024/04/30 16:57

 

查找

顺序查找

逐个扫描包中的元素直至找到相应的元素为止

顺序查找的最坏情况:
对于一个含有n个元素的数组,最坏情况是需要n次数组访问

平均情况:

对于一个含有n个元素的数组中,目标可能在的位置为1~n。如果对每个位置进行一次查找,那么平均查找的次数为(1+n)/2

 

 

二分查找
只有在数组有序时才能被使用

假如查找的方法为search(array,first,size,target)

array为被查找的数组

first数组中要查找部分的起始下标。

Size要查找的元素个数

target目标元素

查找时,先用中间元素与目标元素比较,如果找到就返回

如果中间元素比目标元素小。

那么递归调用search在数组后半部分查找

如果中间元素比目标元素大

那么在数组的前半部分查找

size0时,返回,表示找不到目标元素。

 

开型寻址散列

 

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范围内的所有孪生素数

*定理:若自然数QQ+2不能被不大于根号(Q+2)的任何素数整除,则QQ+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