数据结构(java)之查找

Posted hsiaolung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(java)之查找相关的知识,希望对你有一定的参考价值。

1.        查找

a)       概念:给定某个值,在给定的数据结构中寻找指定数据元素的过程

b)       分类

                     i.            若在查找的同时需要进行插入和删除叫动态查找,否则叫静态查找

                    ii.            从逻辑上说,对应不同数据结构分为线性表、树表、哈希表三种查找技术

c)        效率:通常把查找过程中对关键字执行的平均比较次数ASL作为标准

                i.         ASL=技术分享图片,其中n为节点个数,c为每个节点需要比较的次数

2.        线性查找

a)       顺序查找

                     i.            基本思想:从表的一段开始扫描,若扫描到元素与给定值key相等,结束扫描,返回下标,若扫描完表也没找到,返回-1

                    ii.            代码实现:略

                  iii.            效率:ASL=N

                  iv.            使用范围:在以下两种情况只能采用顺序查找

[1]      顺序表为无序表

[2]      链表

b)       二分查找

                     i.            思想:设置startendmidmid等于中间值,比较mid的值与给定的key值大小,如果mid值大于key,则令end=mid-1,mid=(start+end)/2,如果mid值小于key,则start=mid+1mid=(start+end)/2,继续查找,找到则返回下标,如果start==end还是没找到返回-1

                    ii.            代码实现:略

                  iii.            效率:ASL=log(n+1)-1

                  iv.            使用范围:有序的顺序表

c)        分块查找:索引顺序查找

                     i.            思想:将待排序数组分为几块,每块内求出块内的最大值,然后用key与这些最大值比较,确定key所在的块,然后再在块内顺序查找

                    ii.            代码实现:略

                  iii.            效率:ASL=n^(0.5)

3.        树表查找

a)       提高动态查找表的效率

b)       二叉排序树(二叉查找树)

c)        代码实现:见第五章

d)       查找效率:ASL=logn

4.        哈希表查找

a)       概念:将键值转换为偏移地址来检索记录,键值转换地址通过哈希函数完成

b)       基本思想:假设一个有n个记录的集合设置一个长为m的表,将n个记录的关键字尽可能的转换为0~m-1之间的数值

c)        哈希冲突:不同记录的键值通过哈希函数转换得到的地址相同

d)       构建哈希函数

                     i.            平方取中法,求关键字的平方,然后根据表长度取中间几位数,如关键字为01000110,平方后为00100000012100,假设表长为1000,则取中间三位数字100121

                    ii.            除余法:地址=关键字%pp为小于表长m且最接近m的质数

                  iii.            折叠偏移法:将关键字分为几段,将这几段的值相加,根据表长舍去最高几位得到的地址,如47669,将其拆为1位,3位,1位向加为4+766+9=779,假如表长尾100,则舍去7,地址尾79

e)       解决哈希冲突

                     i.            开放定址法

[1]      首先取一部分数据放入对应地址,当表中i,i+1,…i+k已经存在元素时,如果有后续具有哈希冲突的元素将要放入I,i+1,…i+k的地址时,逐渐向后搜索直到有位置没有插入过元素放入该元素。

                    ii.            链表法

[1]      若选择的表长尾m,则创建一个长度为m由头指针组成的单链表数组,将具有相同哈希值的元素按顺序添加入对应的单链表中

f)         代码实现:以除余法和链表法构建哈希表

//构建哈希节点类

class HashNode{

  privateinte;

  private HashNode next;

  public HashNode() {

     this.e=0;

     this.next=null;

  }

  public HashNode(inte) {

     super();

     this.e = e;

     this.next = null;

  }

  publicint getE() {

     returne;

  }

  publicvoid setE(inte) {

     this.e = e;

  }

  public HashNode getNext() {

     returnnext;

  }

  publicvoid setNext(HashNode next) {

     this.next = next;

  }

}

  //哈希表查找

  publicstaticboolean hashtableSearch(intdata[],intkey) {

     HashNode[] nodes=createHashTable(data);

     inthash=key%getPrimes(data.length);//获取待查找元素的hash

     HashNode temp=nodes[hash];   //hash表中找出待查元素

     while(temp!=null) {

         if(temp.getE()==key)

            returntrue;

         else

            temp=temp.getNext();

     }

     returnfalse;

  }

  //构建哈希表

  publicstatic HashNode[] createHashTable(intdata[]) {

     intlen=data.length;

     inthash;

     intprimes=getPrimes(len);   //找到被除数(小于表长且最接近表长的质数)

     HashNode temp;

     HashNode[] nodes=new HashNode[len];

     for(inti=0;i<len;i++) {

         hash=data[i]%primes;

         temp=nodes[hash];

         HashNode node=new HashNode(data[i]);

         if(temp==null) //如果这是插入该链表的第一个元素,这个节点作为首节点

            nodes[hash]=node;

         else {

            while(temp.getNext()!=null) {

                temp=temp.getNext();

            }

            temp.setNext(node);

         }

     }

 

     returnnodes;

  }

  //求取余法的被除数(小于表长最接近表长的质数)

  publicstaticint getPrimes(intlength) {

     for(inti=length-1;i>1;i--) {

         booleanflag=true;

         for(intj=2;j<i;j++) {

            if(i%j==0) {

                flag=false;

                break;

            }

         }

         if(flag==true)

            returni;

     }

     return -1;

  }

 

g)   性能:在没有哈希冲突的情况下ASL=O(1),随着哈希冲突的增多,会使效率变低

1.        查找

a)       概念:给定某个值,在给定的数据结构中寻找指定数据元素的过程

b)       分类

                     i.            若在查找的同时需要进行插入和删除叫动态查找,否则叫静态查找

                    ii.            从逻辑上说,对应不同数据结构分为线性表、树表、哈希表三种查找技术

c)        效率:通常把查找过程中对关键字执行的平均比较次数ASL作为标准

                i.         ASL=技术分享图片,其中n为节点个数,c为每个节点需要比较的次数

2.        线性查找

a)       顺序查找

                     i.            基本思想:从表的一段开始扫描,若扫描到元素与给定值key相等,结束扫描,返回下标,若扫描完表也没找到,返回-1

                    ii.            代码实现:略

                  iii.            效率:ASL=N

                  iv.            使用范围:在以下两种情况只能采用顺序查找

[1]      顺序表为无序表

[2]      链表

b)       二分查找

                     i.            思想:设置startendmidmid等于中间值,比较mid的值与给定的key值大小,如果mid值大于key,则令end=mid-1,mid=(start+end)/2,如果mid值小于key,则start=mid+1mid=(start+end)/2,继续查找,找到则返回下标,如果start==end还是没找到返回-1

                    ii.            代码实现:略

                  iii.            效率:ASL=log(n+1)-1

                  iv.            使用范围:有序的顺序表

c)        分块查找:索引顺序查找

                     i.            思想:将待排序数组分为几块,每块内求出块内的最大值,然后用key与这些最大值比较,确定key所在的块,然后再在块内顺序查找

                    ii.            代码实现:略

                  iii.            效率:ASL=n^(0.5)

3.        树表查找

a)       提高动态查找表的效率

b)       二叉排序树(二叉查找树)

c)        代码实现:见第五章

d)       查找效率:ASL=logn

4.        哈希表查找

a)       概念:将键值转换为偏移地址来检索记录,键值转换地址通过哈希函数完成

b)       基本思想:假设一个有n个记录的集合设置一个长为m的表,将n个记录的关键字尽可能的转换为0~m-1之间的数值

c)        哈希冲突:不同记录的键值通过哈希函数转换得到的地址相同

d)       构建哈希函数

                     i.            平方取中法,求关键字的平方,然后根据表长度取中间几位数,如关键字为01000110,平方后为00100000012100,假设表长为1000,则取中间三位数字100121

                    ii.            除余法:地址=关键字%pp为小于表长m且最接近m的质数

                  iii.            折叠偏移法:将关键字分为几段,将这几段的值相加,根据表长舍去最高几位得到的地址,如47669,将其拆为1位,3位,1位向加为4+766+9=779,假如表长尾100,则舍去7,地址尾79

e)       解决哈希冲突

                     i.            开放定址法

[1]      首先取一部分数据放入对应地址,当表中i,i+1,…i+k已经存在元素时,如果有后续具有哈希冲突的元素将要放入I,i+1,…i+k的地址时,逐渐向后搜索直到有位置没有插入过元素放入该元素。

                    ii.            链表法

[1]      若选择的表长尾m,则创建一个长度为m由头指针组成的单链表数组,将具有相同哈希值的元素按顺序添加入对应的单链表中

f)         代码实现:以除余法和链表法构建哈希表

//构建哈希节点类

class HashNode{

  privateinte;

  private HashNode next;

  public HashNode() {

     this.e=0;

     this.next=null;

  }

  public HashNode(inte) {

     super();

     this.e = e;

     this.next = null;

  }

  publicint getE() {

     returne;

  }

  publicvoid setE(inte) {

     this.e = e;

  }

  public HashNode getNext() {

     returnnext;

  }

  publicvoid setNext(HashNode next) {

     this.next = next;

  }

}

  //哈希表查找

  publicstaticboolean hashtableSearch(intdata[],intkey) {

     HashNode[] nodes=createHashTable(data);

     inthash=key%getPrimes(data.length);//获取待查找元素的hash

     HashNode temp=nodes[hash];   //hash表中找出待查元素

     while(temp!=null) {

         if(temp.getE()==key)

            returntrue;

         else

            temp=temp.getNext();

     }

     returnfalse;

  }

  //构建哈希表

  publicstatic HashNode[] createHashTable(intdata[]) {

     intlen=data.length;

     inthash;

     intprimes=getPrimes(len);   //找到被除数(小于表长且最接近表长的质数)

     HashNode temp;

     HashNode[] nodes=new HashNode[len];

     for(inti=0;i<len;i++) {

         hash=data[i]%primes;

         temp=nodes[hash];

         HashNode node=new HashNode(data[i]);

         if(temp==null)//如果这是插入该链表的第一个元素,这个节点作为首节点

            nodes[hash]=node;

         else {

            while(temp.getNext()!=null) {

                temp=temp.getNext();

            }

            temp.setNext(node);

         }

     }

 

     returnnodes;

  }

  //求取余法的被除数(小于表长最接近表长的质数)

  publicstaticint getPrimes(intlength) {

     for(inti=length-1;i>1;i--) {

         booleanflag=true;

         for(intj=2;j<i;j++) {

            if(i%j==0) {

                flag=false;

                break;

            }

         }

         if(flag==true)

            returni;

     }

     return -1;

  }

g)   性能:在没有哈希冲突的情况下ASL=O(1),随着哈希冲突的增多,会使效率变低

 

以上是关于数据结构(java)之查找的主要内容,如果未能解决你的问题,请参考以下文章

java 数据结构与算法 之查找法

数据结构(java)之查找

数据结构(java)之查找

数据结构之查找

Java数据结构之双向链表

数据结构之二叉查找树码源以及每一行代码的注释(java实现)