C語言算法 輸出當前集合的所有子集


對輸入的正整數n,輸出{0,1,...,n-1}的所有子集。例如,輸入3時,輸出如下:

{},{0},{1},{0,1},{2},{0,2},{1,2},{0,1,2}

 

這個題目可以考慮用二進制的方法來反映排列組合(輸入數字3對應3位二進制數,3位二進制數共有8種寫法,而包含三個元素的集合的排列組合方式也有8種),就直接拿下面的這個表格來舉例子:

當二進制數為000的時候,默認為空集

當最低位為1其余高位為0的時候,代表當前集合為{0};

當次地位為1其余位為0的時候,代表當前集合為{1};

當高位為1其余低位0的時候,代表當前集合位{2};

以上三種可以任意組合,比如011代表{0,1}、111代表{0,1,2}、010代表{1};

而且這里值得注意的是,二進制對應的數可以組合成有順序的序號

子集 序號trans 對應的二進制數
{} 0 000
{0} 1 001
{1} 2 010
{0,1} 3 011
{2} 4 100
{0,2} 5 101
{1,2} 6 110
{0,1,2} 7 111

直接上代碼:

int main(){
    int num;//這個集合有多少個數
    scanf("%d",&num);
    int cnt=(int)pow(2, num)-1;//實現序號的對應
    
    for(int i=0;i<=cnt;i++){
        printf("{");
        
        int trans=i;//當前的數字
        int set_num=0;//集合中需要填寫的數字
        int comma_sign=0;//逗號
        while (trans) {//根據當前的數字求解其二進制,根據二進制來求集合
            if(trans%2==1){
                if(!comma_sign){
                    printf("%d",set_num);
                    ++comma_sign;
                }
                else{
                    printf(",%d",set_num);
                    ++comma_sign;
                }
            }
            ++set_num;
            trans/=2;
        }
        if(i!=cnt)
            printf("},");
        else
            printf("}");
//
//        if(!((i+1)%5))
//            printf("\n");
    }
    printf("\n");
}

為了解決集合中應該寫入數字幾的問題(比如集合中有1,2,3,此時當前子集是幾個數字,數字是多少的子集組合),這里引入了數字set_num=0變量,當檢測到低位存在數字1的時候,先輸出當前set_num的值0,然后令set_num自加

當再次檢測到次低位存在1到時候,輸出set_num當前的值1,並再次令set_num自加,這是為了如果再次檢測到高位為1的存在的時候可以輸出2

這樣說很抽象,我舉個例子:

當當前序號為7的時候:

7首先會進入while判斷,對7進行2的取余操作得1,那么意味着有低位存在,也就是當前子集當中含0元素,打印當前set_num,接着令set_num自加得1備用

對7進行除2操作(繼續轉2進制)得3賦給原數

3再次進入到while判斷,對3進行2的取余操作得1,那么意味着有次低位存在,也就是當前子集當中含1元素,打印當前set_num,接着令set_num自加備用

。。。

 

重寫了個簡單的版本

    int n=3;
    int combination=1;
    for(int i=1;i<=n;i++)
        combination*=2;
    combination-=1;//根據網上的公式求解子集個數為2^n -1
    
    for(int i=0;i<=combination;i++){//每一種編號都代表一種組合方式
        
        /**
         看那個表,每一個數字都對應一個二進制,例如7用輾轉相處法表示111,每出現一個1,就讓記錄的k自加
         這樣,k由0,變到1,再變到2,則出現了{0,1,2}
         
         當combination等於2的時候,運用輾轉相除法先得到0,那么跳過if(num%2==1),直接++k,由於當前num不等於0
         再進行一輪輾轉,下一次再輾轉求余得到1,打印
         所以結果為{1}
         
         當combination等於3的時候,在while中輾轉求余先得到1,此時打印出sign為{0,當前num為1,sign++
         接着再進入輾轉,符合if條件,打印sign為{0 1
         ...最后得出結果為{0,1}
         */
        int sign=0;
        
        printf("{");
        
        int num=i;
        
        while(num!=0){
            if(num%2==1)
                printf("%d ",sign);
            sign++;//重要
            num/=2;
        }
        
        printf("}");
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM