c语言中的哈希表与时间复杂度

c语言中的哈希表与时间复杂度,c,C,我对c中的hashtable实现相当陌生,我在查看一些访谈问题时发现了一个关于查找数组中元素的奇数出现的问题。我已将所有内容设置为: int a[256]={0}; char *str="hhlloworldd"; int i; for(i=0;i<strlen(str);++i) a[str[i]]++; for(i=0;i<strlen(str);i++) { if(a[str[i]]%2 == 1) { printf("Odd occ

我对c中的hashtable实现相当陌生,我在查看一些访谈问题时发现了一个关于查找数组中元素的奇数出现的问题。我已将所有内容设置为:

int a[256]={0};
char *str="hhlloworldd";
int i;

for(i=0;i<strlen(str);++i)
    a[str[i]]++;

for(i=0;i<strlen(str);i++)
{
    if(a[str[i]]%2 == 1)
    {
        printf("Odd occurrence of %c\n",str[i]);
    }
}
inta[256]={0};
char*str=“hhloworld”;
int i;

对于(i=0;i您的代码似乎有一个bug-但可能我没有正确地获取您的需求:

如果某个字符x在输入中出现奇数次,则第二个for循环将在每次看到它时将其报告为“奇数发生”

您应该将两个for循环合并为一个。 作为旁注,在循环条件中放入O(n)操作(如strlen())取决于编译器是否理解str没有被修改,这样strlen就不会被重复调用,或者最终得到二次性能

int a[256]={0};
int n = strlen(str);
int i;

for(i=0;i<n;++i)
{
    ++a[str[i]];
    if(0 != a[str[i]]%2)
    {
        printf("Odd occurrence of %c\n",str[i]);
    }
}
inta[256]={0};
int n=strlen(str);
int i;

对于(i=0;i您的代码似乎有一个bug-但可能我没有正确地获取您的需求:

如果某个字符x在输入中出现奇数次,则第二个for循环将在每次看到它时将其报告为“奇数发生”

您应该将两个for循环合并为一个。 作为旁注,在循环条件中放入O(n)操作(如strlen())取决于编译器是否理解str没有被修改,这样strlen就不会被重复调用,或者最终得到二次性能

int a[256]={0};
int n = strlen(str);
int i;

for(i=0;i<n;++i)
{
    ++a[str[i]];
    if(0 != a[str[i]]%2)
    {
        printf("Odd occurrence of %c\n",str[i]);
    }
}
inta[256]={0};
int n=strlen(str);
int i;

对于(i=0;i的代码,有两个观察结果:

  • 这与冲突无关,因为没有冲突解决方案
  • 代码的复杂性确实是
    O(n)
    ,但您的分析是错误的:第二个循环的计时是
    O(256)
    ,这是表示
    O(1)
    ,对于
    O(n)
    的总体复杂性的另一种说法

关于您的代码,有两个观察结果:

  • 这与冲突无关,因为没有冲突解决方案
  • 代码的复杂性确实是
    O(n)
    ,但您的分析是错误的:第二个循环的计时是
    O(256)
    ,这是表示
    O(1)
    ,对于
    O(n)
    的总体复杂性的另一种说法
    • 许多评论:

      • 哈希表可以没有冲突。例如,具有完美哈希的哈希表仍然是哈希表。哈希表定义侧重于通过哈希函数(定义就是这样)从键到值的映射。例如,请参见(对于相同的查找数组):

      因此,上面是一个具有完美哈希函数(映射所有元素而不发生冲突)的哈希表,该函数将某些元素(字符)映射为一个值(出现次数)

      • 如前所述,strlen是Θ(n),因此每次循环迭代调用它都会产生Θ(n²)。将strlen从循环中拉出可以解决这个问题

      • 第二个循环是Θ(n),但正如已经评论过的那样,如果这个循环通常是Θ(e)(随着元素数量的增加而增加),则更有意义,在这种情况下是Θ(1)

      • 不可能合并这两个循环。这是因为所有的数组元素只能在处理字符串中的最后一个元素之后才能解释。要理解这一点。如果这不是真的,那么会有一些更早的时刻,我们可以推断出一些散列值已经准备好了。我们处理最后一个元素。如果我们没有处理最后一个元素,那么我们需要将其中一个元素增加1。那么256个桶中的任何一个都可能发生了变化。但是无法猜测是哪一个,我们需要读取最后一个元素。循环结束后,唯一的出路是再次循环

        • 许多评论:

          • 哈希表可以没有冲突。例如,具有完美哈希的哈希表仍然是哈希表。哈希表定义侧重于通过哈希函数(定义就是这样)从键到值的映射。例如,请参见(对于相同的查找数组):

          因此,上面是一个具有完美哈希函数(映射所有元素而不发生冲突)的哈希表,该函数将某些元素(字符)映射为一个值(出现次数)

          • 如前所述,strlen是Θ(n),因此每次循环迭代调用它都会产生Θ(n²)。将strlen从循环中拉出可以解决这个问题

          • 第二个循环是Θ(n),但正如已经评论过的那样,如果这个循环通常是Θ(e)(随着元素数量的增加而增加),则更有意义,在这种情况下是Θ(1)

          • 不可能合并这两个循环。这是因为所有的数组元素只能在处理字符串中的最后一个元素之后才能解释。要理解这一点。如果这不是真的,那么会有一些更早的时刻,我们可以推断出一些散列值已经准备好了。我们处理最后一个元素。如果我们没有处理最后一个元素,那么我们需要将其中一个元素增加1。那么256个桶中的任何一个都可能发生了变化。但是无法猜测是哪一个,我们需要读取最后一个元素。循环结束后,唯一的出路是再次循环


          这是一个简单的数组-将其称为哈希表有点牵强。1)我将其称为直方图。2)我将使用无符号类型进行计数2)我不会重复调用strlen()3)我将使用大小t表示长度4)通常,char是有符号的,数组中的负索引肯定会使事情变得非常糟糕。这是一个简单的数组-称之为哈希表有点夸张。1)我称之为直方图。2) 我会对计数使用无符号类型2)我不会重复调用strlen()3)我会对长度使用size\t 4)通常,char是有符号的,在