C实现 从含有m个元素的集合中取出只含n个元素的子集

该博客介绍了如何从一个包含m个元素的集合中,每次取出n个元素形成子集,并通过C语言实现了一个算法,该算法通过调整元素位置和加1操作,有效地生成所有可能的子集组合。博客重点讨论了算法的逻辑和代码实现,包括关键的position变量的管理和元素排序调整。
摘要由CSDN通过智能技术生成

问题引入

        假设有一个集合U,在集合U中共含有m个元素。如果要从这m个元素中,每次取出n个元素组成只含有n个元素的子集,应该如何实现???

问题分析

        假设集合U中含有5个元素,即U={1,2,3,4,5}。

        现在从U中每次取n=3个元素组成集合U的子集,则可能的取值情况如下所示:

        {1,2,3}、{1,2,4}、{1,2,5}、{1,3,4}、{1,3,5}、{1,4,5}、{2,3,4}、{2,3,5}、{2,4,5}、{3,4,5},

        这些子集中的元素已经经过排序,那么如何实现取数同时又要确保数字为3个并不断右移?通过上述例子不难发现:在取数过程中,如果集合中最右边一个元素小于m,为了实现取数,类同于码表一样不断加1;如果右边一位已是最大值,则加1的位置往左移。每次加1的位置往左移后,必须重新调整右边的元素顺序。问题的关键就在于在哪个位置进行加1。

        为更高效的编写程序,定义一个变量positon记录加1的位置,position的初值设定为n-1, 因为要使用数组,而最右边的索引值为最大的n-1(数组长度)。(例如最初5个元素中取3个元素组成子集,之后不看1,从2、3、4、5中取3个元素组成子集,那么m相当于为4)。因此,在position位置的值小于m就加1,也即往右移一个位置;如果大于m就减1,也即往左移一个位置。由于位置左移后,右边的元素会经过调整,所以我们必须检查最右边的元素是否小于m,如果是,则position调整回n-1,如果不是,则positon维持不变。

代码实现

#include <stdio.h>
#include <stdlib.h>
#define MAX 20 //设置子集数判断数组容量,可根据需求修改 

int main(){
	int set[MAX];
	int m, n, position; 
	int i;
	printf("请输入集合U中含有的元素个数 m:"); 
	scanf("%d", &m); 
	printf("请输入从集合U取出几个元素组成集合U的子集 n:"); 
	scanf("%d", &n);
	for(i = 0; i < n; i++){
		set[i] = i + 1;
	}
	
	// 显示第一个集合
	for(i = 0; i < n; i++){
		printf("%d ", set[i]);
	}
	putchar('\n'); 
	position = n - 1;
	while(1){
		if(set[n-1] == m){
			position--;
		}else{
			position = n - 1;
		}
		set[position]++;
		// 调整右边元素
		for(i = position + 1; i < n; i++){
			set[i] = set[i-1] + 1;
		}
		
		for(i = 0; i < n; i++){
			printf("%d ", set[i]);	
		}
		putchar('\n');
		if(set[0] >= m - n + 1){
			break;
		}
	}
	return 0;
}

运行结果

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等日出看彩虹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值