C 寻找整数的正确后代

C 寻找整数的正确后代,c,algorithm,binary,proper,C,Algorithm,Binary,Proper,我被困在一个基本的算法问题上,我不知道如何解决它 基本上我想列出所有整数的正确后代。也就是说,如果我的数字是21,我想使用它的二进制表示(10101),列出所有至少有一个公共位值为1和21且小于21的数字。这里的结果应该是101001000110001100 正确后代的数学定义如下: 设h是小于2^m的非负数h=d0+d1*2^1+…+dm-1*2^(m-1)其中di=0或1 设h'为另一非负,如h'=d0'+d1'*2^1+…+dm-1'*2^(m-1)其中di'=0或1 h'是h的后代

我被困在一个基本的算法问题上,我不知道如何解决它


基本上我想列出所有整数的正确后代。也就是说,如果我的数字是21,我想使用它的二进制表示(10101),列出所有至少有一个公共位值为1和21且小于21的数字。这里的结果应该是101001000110001100

正确后代的数学定义如下:

  • 设h是小于2^m的非负数<代码>h=d0+d1*2^1+…+dm-1*2^(m-1)其中di=0或1

  • 设h'为另一非负,如
    h'=d0'+d1'*2^1+…+dm-1'*2^(m-1)
    其中di'=0或1


  • h'是h的后代,如果di'好的话,那么我最终用C编写了一个代码,它看起来很不好看,可能经过了可怕的优化,但仍然可以正常工作。可能有更简单的解决方案,但出于知识目的,这里是我的:

    #include <stdio.h>
    #include <stdbool.h>
    #include <stdlib.h>
    unsigned int pui(unsigned int a, unsigned int b)
    {
      if (b == 0)
        return 1;
      if (b == 1)
        return a;
      if (b % 2 == 0)
        return pui(a * a, b / 2);
      else
        return pui(a * a, (b - 1) / 2);
    }
    unsigned int testBit(unsigned int h, unsigned int offset)
    {
      unsigned int mask = 1 << offset;
      return (h & mask);
    }
    
    bool isInList(unsigned int x, unsigned int *output_size, unsigned int **output)
    {
      for (int i = 0; i < *output_size; i++)
      {
        if (*(*output + i) == x)
        {
          return true;
        }
      }
      return false;
    }
    void listDescendants(unsigned int h, unsigned int *output_size, unsigned int **output, int *currently_processing)
    {
      unsigned int max_offset = 0;
      unsigned int temp_h = h;
      unsigned int initial_output_size = *output_size;
      while (temp_h > 0)
      {
        max_offset++;
        temp_h /= 2;
      }
      unsigned int h_radix2[max_offset];
      for (int i = 0; i < max_offset; i++)
      {
        if (testBit(h, i))
        {
    
          if (h > pui(2, i) && !isInList(h - pui(2, i), output_size, output))
          {
            *(*output + *output_size) = h - pui(2, i);
            *output_size += 1;
          }
        }
      }
    
      if (*currently_processing < (int)*output_size)
      {
        *currently_processing += 1;
        listDescendants(*(*output + *currently_processing), output_size, output, currently_processing);
      }
    }
    
    
    int main()
    {
      
      int currently_processing = -1;
      unsigned int size = 0;
      unsigned int *output = malloc(300 * sizeof(unsigned int));
      listDescendants(21, &size, &output, &currently_processing);
    
      printf("size = %u\n", size);
      for (int i = 0; i < size; i++)
      {
        printf("%u ", output[i]);
      }
      printf("\n");
    
      return 0;
    }
    
    #包括
    #包括
    #包括
    无符号整数pui(无符号整数a、无符号整数b)
    {
    如果(b==0)
    返回1;
    如果(b==1)
    返回a;
    如果(b%2==0)
    返回pui(a*a,b/2);
    其他的
    返回贝氏指数(a*a,(b-1)/2);
    }
    无符号整数测试位(无符号整数h,无符号整数偏移)
    {
    无符号整数掩码=1(0)
    {
    最大偏移量++;
    温度h/=2;
    }
    无符号整数h_半径2[最大偏移量];
    对于(int i=0;ipui(2,i)和&!isInList(h-pui(2,i),输出大小,输出))
    {
    *(*输出+*输出大小)=h-pui(2,i);
    *输出_大小+=1;
    }
    }
    }
    if(*当前处理<(整数)*输出大小)
    {
    *当前_处理+=1;
    列表子体(**输出+*当前处理)、输出大小、输出、当前处理);
    }
    }
    int main()
    {
    int当前_处理=-1;
    无符号整数大小=0;
    无符号整数*输出=malloc(300*sizeof(无符号整数));
    列表子体(21、大小、输出和当前处理);
    printf(“大小=%u\n”,大小);
    对于(int i=0;i
    您可以使用递归解决方案,如以下解决方案

    我有点懒,所以我没有把数字放在列表中,只是简单地打印出来,而且我还打印了0和给定的数字

    我相信你可以很容易地调整代码,让它做你想要的

    #include <stdio.h>
    
    #define CHAR_BIT 8
    
    void ProperDescendantsRecursive(unsigned int num, unsigned int bit_index)
    {
        if (CHAR_BIT * sizeof(unsigned int) - 1 == bit_index)
        {
            printf("%u\n", num);
        }
        else
        {
            unsigned int mask = 1U << bit_index;
            if (num & mask)
            {
                /* with the bit at index bit_index is off */
                ProperDescendantsRecursive(num ^ mask, bit_index + 1);
                /* with the bit at index bit_index is on */
                ProperDescendantsRecursive(num, bit_index + 1);
            }
            else
            {
                ProperDescendantsRecursive(num, bit_index + 1);
            }
        }
    }
    
    void ProperDescendants(unsigned int num)
    {
        ProperDescendantsRecursive(num, 0);
    }
    
    int main(void)
    {
        ProperDescendants(21);
        
        return 0;
    }
    

    这里有一个非常简单的方法:枚举
    n-1
    1
    之间的所有整数,并打印那些严格包含在
    n
    中的整数,即:
    (i&n)=i

    void list_descendants(int n) {
        printf("descendants of %d:", n);
        for (int i = n; i --> 1;) {
            if ((i & n) == i)
                printf(" %d", i);
        }
        printf("\n");
    }
    

    我们很高兴您与我们在一起,我们需要查看您的代码以帮助您调试它。如果你没有algo,请先开发它。这里有一个想法:检查所有
    1
    位,将它们逐个归零。然后,对于每个结果,递归运行算法以查找“后代”的“后代”。“列出至少有一个公共位值为1的所有数字”,则正确答案还包括11、111等。您的规范中有错误。
    &
    在Python和C中是您的朋友将原始数据分解为2的幂(21=16+4+1),对这些进行一次计算,对于幂集中的每个集进行一次求和,求和列表就是您想要的后代列表。只是想知道
    pui
    是什么。而
    #include
    s在哪里?pui只是一个基本的求幂函数(pui(2,i)返回2^i)。我忘了把文件放进去。包括以下内容(将它们添加到文件中):#包括#包括#包括
    pui
    是过分的。您可以编写2^n作为
    1第一次打印缺少参数,但我认为这是最好的解决方案。非常感谢。
    
    void list_descendants(int n) {
        printf("descendants of %d:", n);
        for (int i = n; i --> 1;) {
            if ((i & n) == i)
                printf(" %d", i);
        }
        printf("\n");
    }