C语言实现之列举非空真子集

本文介绍如何使用C语言实现列举给定集合(如A{a,b,c,d,e,f})的所有非空真子集。通过分析组合问题,采用递归方法,从1个元素开始直至N-1个元素,生成2^N - 2个子集。代码实现简洁,最终展示完整的子集列表。" 104660909,9086920,LeetCode994: 腐烂橘子的最小扩散时间,"['算法', 'LeetCode', '数据结构', '广度优先搜索', '网格问题']

题目:

        已知集合A{a,b,c,d,e,f},要求列举出此集合的所有非空真子集。

分析:

    因为集合有无序性,所以要列举所有的非空真子集其实就是一个组合问题。从中找出1个元素的组合,然后是2个的,再然后是3个的,知道N-1个的,第N个就是他自己了,是子集但不是真子集,所以不用算,所以需要我们列举的有2^N - 2个集合。

思路:

    我是这样想的,建立一个数组,记录元素的位置,这样不管元素是什么字符,我们只用管位置这个数字就行了,先从第一个元素开始,到达指定长度则打印出这一组位置的组合,即A集合的一个子集,之后开始位置从第二个再开始,依次循环递归下去,直到最后长度和集合A的长度相同。

实现:

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

char *A = "abcdef";     //集合元素
int eCount = 0;         //存储集合中的元素个数
int * sortArr = NULL;   //存储元素排列的数组


/**********************************
*函  数:void opt(int length)      *
*参  数:元素长度                   *
*功  能:输出一个指定长度的元素       *
*返  回:无                        *
***********************************/
void opt(int length)
{
    int loop = 0;
    //循环输出一个真子集中的集合元素
    for(;loop < length; loop++)
    {
        printf("%c", A[sortArr[loop]]);
    }
    puts("");                           //换行,方便观察
}


/*********************************************************
*函  数:void trvl(int length, int nowlength, int site)   *
*参  数:集合长度,当前长度,当前位置                         *
*功  能:递归组合集合中指定长度的真子集                       *
*返  回:无                                               *
**********************************************************/
void trvl(int length, int nowlength, int site)
{
    //判断当前长度是否到达指定集合长度(到达的话,就不再向下执行)
    if(nowlength == length)
    {
        opt(length);                            //输出此次递归的集合元素
        return;                                 //结束此次调用
    }
    //循环递归到当前位置到达集合的最后一个元素的位置
    while(site != eCount)
    {
        sortArr[nowlength] = site;              //记录当前位置
        trvl(length, nowlength + 1, ++site);    //继续递归产生下一个位置
    }
}


/**********************
*函  数:int main()    *
*参  数:无            *
*功  能:主函数         *
*返  回:执行结果       *
**********************/
int main()
{
    int loop = 1;
    eCount = strlen(A);                                     //计算集合元素个数
    sortArr = (int *)malloc(sizeof(int) * eCount);          //生成存储元素排列的数组
    if(sortArr == NULL)
    {
        puts("not have enough memory.");
        exit(-1);
    }

    //循环遍历指定长度的子集
    for(;loop < eCount; loop++)
    {
        trvl(loop, 0, 0);                                   //递归遍历子集
    }

    free(sortArr);                                          //释放掉申请存储元素排列的数组的内存空间

    return 0;
}

结果:

        a
        b
        c
        d
        e
        f
        ab
        ac
        ad
        ae
        af
        bc
        bd
        be
        bf
        cd
        ce
        cf
        de
        df
        ef
        abc
        abd
        abe
        abf
        acd
        ace
        acf
        ade
        adf
        aef
        bcd
        bce
        bcf
        bde
        bdf
        bef
        cde
        cdf
        cef
        def
        abcd
        abce
        abcf
        abde
        abdf
        abef
        acde
        acdf
        acef
        adef
        bcde
        bcdf
        bcef
        bdef
        cdef
        abcde
        abcdf
        abcef
        abdef
        acdef
        bcdef

总结:

       这个用递归的思路很简单,但想起来具体怎么递归的就有点乱了,虽然只有不到10行的东西。当然大家如果有更简单的方法,希望你告诉我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值