如何实现n元素的搜索和插入操作的动态二进制搜索

时间:2010-04-08 17:31:08

标签: c algorithm arrays binary-search

这个想法是使用多个数组,每个长度为2 ^ k,根据n的二进制表示来存储n个元素。每个数组都被排序,不同的数组不以任何方式排序。

在上述数据结构中,SEARCH通过每个阵列上的二进制搜索序列来执行。 INSERT由一系列相同长度的数组合并执行,直到达到空数组。

更多细节:让我们假设我们有一个长度为2 ^ k的垂直数组,并且该数组的每个节点都附加了长度为2 ^ k的水平数组。

也就是说,对于垂直阵列的第一个节点,连接一个长度为2 ^ 0 = 1的水平阵列,对于垂直阵列的第二个节点,连接一个长度为2 ^ 1 = 2的水平阵列,依此类推。因此,首先在第一个水平阵列中执行插入,对于第二个插入,第一个阵列变为空,第二个水平阵列充满2个元素,第三个插入第一个和第二个阵列水平。数组被填充等等。  我实现了搜索的常规二进制搜索,并按如下方式插入:

int main()
  {
   int a[20]= {0}; 
    int n, i, j, temp;
    int *beg, *end, *mid, target;

   printf(" enter the total integers you want to enter (make it less then 20):\n");
    scanf("%d", &n);
   if (n >= 20) return 0;      
   printf(" enter the integer array elements:\n" );
    for(i = 0; i < n; i++)
    {

      scanf("%d", &a[i]);
    }

    // sort the loaded array, binary search! 
    for(i = 0; i < n-1; i++)    
    {  
      for(j = 0; j < n-i-1; j++)
      {
        if (a[j+1] < a[j])
       {
          temp = a[j];
          a[j] = a[j+1];
          a[j+1] = temp;
        }
      }
    }
    printf(" the sorted numbers are:");
    for(i = 0; i < n; i++)
    {
      printf("%d ", a[i]);
    }

    // point to beginning and end of the array
    beg = &a[0];
    end = &a[n];  // use n = one element past the loaded array!
    // mid should point somewhere in the middle of these addresses
    mid = beg += n/2;


    printf("\n enter the number to be searched:");
    scanf("%d",&target);

    // binary search, there is an AND in the middle of while()!!!
    while((beg <= end) && (*mid != target))
    {
      // is the target in lower or upper half?
      if (target < *mid)
      {
        end = mid - 1;     // new end
        n = n/2;
        mid = beg += n/2;  // new middle
      }
      else
      {
        beg = mid + 1;     // new beginning
        n = n/2;
        mid = beg += n/2;  // new middle      
      }
    }

    // find the target?
    if (*mid == target)
    {
      printf("\n %d found!", target);
    }
    else
   {
      printf("\n %d not found!", target);
    }

    getchar();  // trap enter
    getchar();  // wait
    return 0;
  }

有人可以建议如何修改此程序或新程序以实现如上所述的动态二进制搜索!!

2 个答案:

答案 0 :(得分:1)

闻起来像家庭作业,因为通常有更好的方法来实现设计。

让我澄清一下要求: 给定一组连续的整数,可以认为它们按以下顺序排列:

row 0: array[0] #
row 1: array[1] # #
row 2: array[3] # # # #
row 3: array[7] # # # # # # # #

根据我的理解,搜索算法是:

<强> 1。外部二进制搜索

将二进制搜索应用于第一个“列”。 结果将找到要搜索的行。

<强> 2。行二进制搜索

将二进制搜索应用于该行以查找确切的值。

外部二进制搜索

下一步是修改现有的二进制搜索算法,根据数组布局推进“最低”和“最高”索引。

查看上面的布局,似乎每个行的数组索引都有一个模式。看起来像:

  [Equation 1] index = power(2, row #) - 1

在二分搜索中,每次迭代都会选择一个中点,该点位于最高点和最低点之间,通常计算如下:

[Equation 2} midpoint = ((highest - lowest) / 2) + lowest

为了使理解更容易,让我们采用两种索引约定:行索引列索引。根据布局,行索引是行号。 列索引将是行内的位置。上面的布局包含4行。第2行有4列。

因此,为了找到行,我们使用中点公式:

   row_midpoint = ((row_highest + row_lowest) / 2) + row_lowest

在比较值之前,必须首先找到它。通过将 row_midpoint 值插入等式1来获得该位置。

array_midpoint_index = (1 << row_midpoint) - 1

然后使用此 array_midpoint_index 获取该值:     value = array [array_midpoint_index]

为避免重复计算,建议您保存值,例如 row_low_value row_high_value 作为示例。

找到确切的行后,是时候了......

行二进制搜索

应用于该行的二进制搜索是扩充二进制搜索。增强是确定行的第一列和最后一列的数组索引。可以使用公式1计算这些列索引。

详细信息留给读者练习 (顺便说一句,制作图片和图表在遇到问题时总是一个有用的做法,无论是计算机算法还是物理上的单词问题。)

维护数据结构

通过将其作为单个阵列处理,可以最简单地执行此数据结构的维护,插入和删除元素。找到插入索引后,将元素向下移动为另一个元素腾出空间,然后插入新元素。

更好的数据结构

更好的数据结构可能是一个[value, pointer, length]元素数组。指针指向另一个数组。 length 字段表示数组的长度。这允许在值字段上使用标准二进制搜索。可以使用指针 length 字段将标准二进制搜索应用于数组。方便的是C和C ++语言带有标准的二进制搜索功能,已经过测试,你不必浪费时间重写

答案 1 :(得分:1)

动态二进制搜索确实是一种很酷的算法。它的参考是算法导论(Cormen,Leiserson和Rivest)问题18-2,它与在线合并(Knuth TAOCP ex 5.2.4-17)密切相关。它具有O(log(n))平均成功搜索时间。最坏情况下成功和不成功的搜索都是O(log 2 (n))。并且比平衡搜索树更容易编码。

搜索非常简单,您只需搜索每一行,直到找到某些内容(从最大的开始)。我在下面实现了插入。合并例程执行所有排序。请注意,每行都是一个int *,它与一个int数组(或NULL)相同。如果我正在制作一个高性能版本,我会考虑将一些较小的数组缓存为malloc,而free则往往会很慢。


int *row[30];
int lastrow=0;
void dbs_insert(int v);
int *dbs_merge(int *a, int *b, int len);

void dbs_insert(int v) {
    int *new_row;
    int i;
    new_row=malloc(sizeof(int));
    new_row[0]=v;
    i=0;
    while (row[i]!=NULL) {
        new_row=dbs_merge(row[i],new_row,1<<i);
        row[i]=NULL;
        i++;
    }
    row[i]=new_row;
    if (i>lastrow) lastrow=i;
}

int *dbs_merge(int *a, int *b, int len) {
    int ai=0;
    int bi=0;
    int ci=0;
    int *c;
    c=malloc((2*len)*sizeof(int));
    while (ai <len && bi < len) {
        if (a[ai]<=b[bi]) {
            c[ci++]=a[ai++];
        } else {
            c[ci++]=b[bi++];
        }
    }
    while (ai<len)
        c[ci++]=a[ai++];
    while (bi<len)
        c[ci++]=b[bi++];
    free(a);
    free(b);
    return c;
}