搜索算法(顺序、二分、索引)

搜索算法

平均查找长度ASL

A S L = P 1 C 1 + P 2 C 2 + . . . + P n C n ASL = P_{1}C_{1} + P_{2}C_{2} + ...+ P_{n}C_{n} ASL=P1C1+P2C2+...+PnCn
P_{n}: 查找第n个元素的概率
C_{n}:查找第n个元素的比较次数

常见的查询算法

  • 顺序查找
  • 二分查找
  • 索引查找
  • 哈希查找

1. 顺序查找

复杂度分析:
  • 最好情况: O(1)
  • 最差情况: O(n)
  • A S L = 1 n ∑ i = 1 n i = n + 1 2 ASL = \frac{1}{n}\sum_{i=1}^{n}i = \frac{n+1}{2} ASL=n1i=1ni=2n+1

代码:

typedef int ElemType;
int seqSearch(ElemType *table, int length, ElemType target){
  int i;
  for(i = 0; i < length ; i++){
    if(table[i] == target){
      return i;
    }
  }
  return -1;
}

2. 二分查找(折半)

要求

有序表

复杂度分析:
  • 最好情况: O(1)
  • 最差情况: O( l o g 2 n + 1 log_{2}n +1 log2n+1)
  • ASL: 假设为满二叉树: 树高 h = l o g 2 ( n + 1 ) h = log_{2}(n+1) h=log2(n+1)
    A S L = 1 n ∑ i = 1 h i ∗ 2 i − 1 = n + 1 n l o g 2 ( n + 1 ) − 1 ASL = \frac{1}{n} \sum_{i = 1}^{h}i *2^{i-1} = \frac{n+1}{n}log_{2}(n+1)-1 ASL=n1i=1hi2i1=nn+1log2(n+1)1

代码:

typedef int ElemType;
int binarySearcch(ElemType *table, int length, ElemType target) {
  if(length <= 0) return -1;
  int low = 0, high = length - 1, mid = (high + low) / 2;

  while(low <= high) {
    if(target == table[mid]) return mid;
    else if(target < table[mid])
      high = mid -1;
    else low = mid + 1;

    mid = (low + high) / 2;
  }
  return -1;
}

3. 索引查找

要求

  • 建立索引, 根据索引定位, 每个索引划分一个块
  • 索引有序, 每个块内部也有序
  • 对索引表和每个块内都可以进行顺序查找或者二分查找
  • 即在索引表中查找, 再到块中查找.
复杂度分析:
  • 假设索引和快内都采用顺序搜索:
  • ASL = ASL(索引表) + ASL(块内)
  • 设表长为n, 每个块有r个元素, 可以分为s个块 , 粗略来说: r = n s r = \frac{n}{s} r=sn
    A S L = 1 s ∑ i = 1 s i + 1 r ∑ j = 1 r j = s + r + 2 2 = 1 2 ( n s + s ) + 1 ASL = \frac{1}{s} \sum_{i = 1}^{s}i +\frac{1}{r} \sum_{j = 1}^{r}j = \frac {s+r+2}{2} = \frac{1}{2}(\frac{n}{s}+s)+1 ASL=s1i=1si+r1j=1rj=2s+r+2=21(sn+s)+1

代码:

typedef int Elemtype;

typedef struct index{
  Elemtype key;
  int index;
}Index;

int indexSearch(vector <Index> indexVec, Elemtype *table, Elemtype target) {
  //索引表中最后一个元素存储的index为table的最后一个元素的下标
  int i = 0;
  while(i < indexVec.size() - 1 && target > indexVec[i].key) i++;
  if( i == indexVec.size() - 1) return -1;

  int j = indexVec[i].index;
  // printf("块:%d\n",i );

  while(table[j] != target && j < indexVec[i+1].index) j++;
  if(target == table[j]) return j;
  return -1;
}

你可能感兴趣的:(搜索算法,C++)