actanble

导航

Algorithm Gossip (29) 产生可能的集合

前言

This Series aritcles are all based on the book 《经典算法大全》; 对于该书的所有案例进行一个探究和拓展,并且用python和C++进行实现; 目的是熟悉常用算法过程中的技巧和逻辑拓展。

提出问题

29.Algorithm Gossip:产生可能的集合

说明

给定一组数字或符号 , 产生所有可能的集合(包括空集合 ), 例如给定1 2 3 , 则可能的集合为 :{}、{1}、{1,2}、{1,2,3}、{1,3}、{2}、{2,3}、{3}。

解法

如果不考虑字典顺序,则有个简单的方法可以产生所有的集合,思考二进位数字加法,并注意1出现的位置,如果每个位置都对应一个数字,则由1所对应的数字所产生的就是一个集合,例如:了解这个方法之后,剩下的就是如何产生二进位数?有许多方法可以使用,您可以使用unsigned型别加上&位元运算来产生,这边则是使用阵列搜 寻,首先阵列内容全为0,找第一个1,在还没找到之前将走访过的内容变为0,而第一个找到的0则变为 1,如此重复直到所有的阵列元素都变为1为止

分析和解释

代码

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 20
int main(void) {
	char digit[MAXSIZE];
	int i, j;
	int n;
	printf("输入集合个数:");
	scanf("%d", &n);
	for(i = 0; i < n; i++)
		digit[i] = '0';
	printf("\n{}"); // 空集合
	while(1) {
		// 找第一个0,并将找到前所经过的元素变为0
		for(i = 0; i < n && digit[i] == '1'; digit[i] = '0', i++);
		if(i == n) // 找不到0
			break;
		else // 将第一个找到的0变为 1
		digit[i] = '1';
		// 找第一个1,并记录对应位置
		for(i = 0; i < n && digit[i] == '0'; i++);
		printf("\n{%d", i+1);
			for(j = i + 1; j < n; j++)
				if(digit[j] == '1')
				printf(",%d", j + 1);
			printf("}");
		}
	printf("\n");
	return 0;
}
///////C(字典顺序)//////////////
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 20
int main(void) {
	int set[MAXSIZE];
	int i, n, position = 0;
	printf("输入集合个数:");
	scanf("%d", &n);
	printf("\n{}");
	set[position] = 1;
	while(1) {
		printf("\n{%d", set[0]); // 印第一个数
			for(i = 1; i <= position; i++)
				printf(",%d", set[i]);
			printf("}");
		if(set[position] < n) { // 递增集合个数
			set[position+1] = set[position] + 1;
			position++;
			}
		else if(position != 0) { // 如果不是第一个位置
			position--; // 倒退
			set[position]++; // 下一个集合尾数
			}
		else // 已倒退至第一个位置
			break;
		}
	printf("\n");
	return 0;
}

拓展和关联

后记

参考书籍

  • 《经典算法大全》
  • 维基百科

posted on 2017-04-14 21:11  白于空  阅读(207)  评论(0编辑  收藏  举报