求集合的子集

原创 2015年07月07日 20:34:27
#include "iostream"
using namespace std;
/*
功能:求集合的子集
描述:求一个集合的所有子集,如集合{1,2,3},则它的子集为
	{},{1},{2},{1,2},{3},{1,3},{2,3},{1,2,3}。
解决:集合的所有子集的个数为2^n,时间复杂度为2^n,空间复杂度做到n,
	用二进制来表示子集。此算法为优解,不重复一个也不漏掉一个。
详细:比如有集合{1,2,3},则子集对应的二进制为:000, 100,010,110,001,101,011,111。
    取出位为1对应的数:000-->{}, 100-->{1}, 010-->{2}, 110-->{1,2}, 001-->{3}, 101-->{1,3}, 
	011-->{2,3}, 111-->{1,2,3}。
缺陷:从000到111我们用位移<<的方式来表示,但若这个集合很大,超过64了就不能用位移了,
	这样的话我们就自定义的一个跟集合一样大的数组,值为0或者1,来模拟二进制。

扩展:求所有子集元素的和为SUM的子集。

优化:模拟“<<”操作符的MoveToNext函数待以后优化。

版本:VS1.0 Create By Duz on 2015.7.7
*/

/* 集合大小200 */
#define NUM 200

/* 子集元素和为10的子集 */
#define SUM 10

/* 需要的子集个数 */
#define GATHER_NUM 5

//数据入口
void init(int *a);
void init(int *a, char *filename){}

//判断是否为最后一个子集
bool isEnd(int *a);

//模拟位移<<1,这个算法唯一可优化的地方就在于这个函数,留后续空余时间优化。
void MoveToNext(int *a);
void print(int *a);

int main(int argc, char **argv)
{
	int a[NUM] = {0}; //集合
	int index[NUM] = {0}; //集合对应的位
	int sum = 0;   //子集的和
	int resultNum = 0; //得到的子集的个数

	//读入集合数据
	init(a);

	while (1){
		sum = 0;
		//移位
		MoveToNext(index);  
		//得到子集的和
		for (int i = 0; i < NUM; i++){
			if (index[i]){
				sum += a[i];
			}

		}
		//如果子集和为所需,则输出结果。
		if (SUM == sum){
			resultNum++;
			for (int i = 0; i < NUM; i++){
				if (index[i]){
					cout << a[i] << " ,";
				}
			}
			cout << endl;
		}
		//得到了所需的子集个数,退出
		if (GATHER_NUM == resultNum){
			break;
		}
		//所有的子集都取完了
		if (isEnd(index)){
			break;
		}
	}

	system("pause");
	return 0;
}

void MoveToNext(int *a)
{
	for (int i = 0; i < NUM; i++){
		if (0 == *(a + i)){ //1,找到第一个为0的位
			//2,将第一个为0的为置为1
			*(a + i) = 1;
			//3,之前的位全部置为0
			memset(a, 0x00, i * sizeof(int));
			break;
		}
	}
}

bool isEnd(int *a)
{
	for (int i = 0; i < NUM; i++){
		if (0 == *(a + i)){
			return false;
		}
	}
	return true;
}

void init(int *a)
{
	for (int i = 0; i < NUM; i++){
		*(a + i) = rand() % 10;
	}
}

void print(int *a)
{
	for (int i = 0; i < NUM; i++){
		cout << *(a + i) << ",";
	}
	cout << endl;
}

相关文章推荐

求集合的所有子集问题

  • 2009年03月15日 18:16
  • 174KB
  • 下载

回溯法 求集合全排列、子集

回溯法,参见之前的blog。 全排列: 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。 从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如...

求集合的所有子集

  • 2015年09月20日 01:32
  • 856B
  • 下载

使用回溯法求集合的子集

  • 2010年07月05日 22:30
  • 711KB
  • 下载

两种求集合所有子集的方法

假设我们有一个求集合的全部子集(包含集合自身)的需求,即有一个集合s,包含两个元素 ,则其全部的子集为. 不难求得,子集个数sn与原集合元素个数n之间的关系为:sn=2^n-1。   本文分别讲述两种...

C/C++ 求一个集合的子集

  • 2012年04月02日 17:26
  • 538B
  • 下载

求一个集合子集的算法示例

  • 2014年06月14日 21:26
  • 464KB
  • 下载

回溯法——集合求子集

#include #include using namespace std; template class Subset { public: void Input(void); //输入集合A中的...

求集合的所有子集的算法

求集合的所有子集的算法对于任意集合A,元素个数为n(空集n=0),其所有子集的个数为2^n个如集合A={a,b,c},其子集个数为8;对于任意一个元素,在每个子集中,要么存在,要么不存在,对应关系是:...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:求集合的子集
举报原因:
原因补充:

(最多只允许输入30个字)