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.            思想:设置start、end、mid,mid等于中间值,比较mid的值与给定的key值大小,如果mid值大于key,则令end=mid-1,mid=(start+end)/2,如果mid值小于key,则start=mid+1,mid=(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.            平方取中法,求关键字的平方,然后根据表长度取中间几位数,如关键字为0100、0110,平方后为0010000、0012100,假设表长为1000,则取中间三位数字100、121

                    ii.            除余法:地址=关键字%p,p为小于表长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.            思想:设置start、end、mid,mid等于中间值,比较mid的值与给定的key值大小,如果mid值大于key,则令end=mid-1,mid=(start+end)/2,如果mid值小于key,则start=mid+1,mid=(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.            平方取中法,求关键字的平方,然后根据表长度取中间几位数,如关键字为0100、0110,平方后为0010000、0012100,假设表长为1000,则取中间三位数字100、121

                    ii.            除余法:地址=关键字%p,p为小于表长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),随着哈希冲突的增多,会使效率变低