在具有一些NULL字符串的有序字符串数组中查找字符串

时间:2014-08-12 11:40:41

标签: c arrays string

字符串数组按排序顺序给出,但它们之间可以包含任意数量的空字符串。我需要搜索该字符串数组中的字符串。如果找到string,则返回该索引,否则返回-1。

我使用strcmp()编写了下面的代码,该代码适用于没有NULL字符串的字符串数组。如何扩展它以适用于具有Null字符串的数组。

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>

int search(char *arr[], char *strtofind, int l, int r)
{
    int mid , val;
    if(l <= r)
    {
        mid = (l+r)/2;
        val = strcmp(strtofind, arr[mid]);
        if(val == 0)
            return mid;
        else if(val > 0)
        {
            return search(arr, strtofind,mid+1,r);
        }
        else
        {
            return search(arr, strtofind, l, mid-1);
        }
    }
    return -1;
}

int main(int argc, char** argv) 
{

    int idx;
    //char *arr[] = {"STR1", "STR2","STR3","STR4","STR5","STR6","STR7"}; // WORKS HERE
    char *arr[] = {"STR1", "STR2","STR3",NULL,"STR4",NULL,"STR5"};  // NOT WORKS HERE

    idx = search(arr, "STR4", 0, 6);
    printf("Found at = %d\n", idx);

    printf("Will is Everything.");
    return (EXIT_SUCCESS);
}

3 个答案:

答案 0 :(得分:1)

更改比较代码。 NULL中的arr[mid]本质上是“跳过”此元素,因此比较需要线性寻找下一个或前一个元素。

为防止最坏情况导致代码混乱,请确保后续搜索列表的两半不会重新扫描一组NULL元素mid。请注意列表两端的NULL

最糟糕的情况是O(n*n),其中有很多NULL。如果O(n*ln2(n))很少见,则可以预期NULL表现。

此外,不需要递归调用。见评论

int search(const char *arr[], const char *strtofind, int l, int r)
  while (l <= r) {
    int mid = (l+r)/2;
    int right_min = mid + 1;
    while (arr[mid] == NULL) {
      // If entire left side and mid are NULL ...
      if (mid == 0) {
        return search(arr, strtofind, right_min, r);
        // or { l = right_min; continue; }
      }
      mid--;
    }
    int cmp = strcmp(strtofind, arr[mid]);
    if (cmp == 0) {
      return mid;
    }
    if(val > 0) {
      return search(arr, strtofind, right_min, r);
      // or { l = right_min; continue; }
    }
    int left_max = mid - 1;
    return search(arr, strtofind, l, left_max);
    // or { r = left_max; }
  }
  return -1;
}

建议:使用const

如果arr[]所有NULL都在一端,则存在一种有效的方法。 O(n*ln2(n))

答案 1 :(得分:0)

这样的东西会跳过空值。一旦它达到空值,它就会转向线性搜索,但我想不出更好的方法。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int search(char arr[][20], char *strtofind, int l, int r)
{
    int mid , val, down = 1, start;
    if(l <= r)
    {
        mid = (l+r)/2;
        start = mid;
        while(0 == arr[mid])
        {
            if(down)
            {
                if(mid >= l)
                {
                    mid--;
                }
                else
                {
                    down = 0;
                    mid = start;
                }
            }
            else
            {
                if(mid <= r)
                {
                    mid++;
                }
                else
                {
                    return -1;
                }
            }
        }
        val = strcmp(strtofind, arr[mid]);
        if(val == 0)
            return mid;
        else if(val > 0)
        {
            return search(arr, strtofind,mid+1,r);
        }
        else
        {
            return search(arr, strtofind, l, mid-1);
        }
    }
    return -1;
}

int main(int argc, char** argv)
{

    int idx;
    char arr[][20] = {"STR1", "STR2","STR3","STR4"};

    int num = sizeof(arr)/sizeof(arr[0]);
    idx = search(arr, "STR2", 0, num-1);
    if(-1 != idx)
    {
        printf("Found at = %d\n", idx);
    }
    else
    {
        printf("Not found");
    }
    return (EXIT_SUCCESS);
}

答案 2 :(得分:0)

执行strcmp()时,请检查NULL。如果为NULL则转到that_index-1。它会起作用。