通用"选子集"算法!

wqfclz 2004-07-23 05:45:36
假定有一个集合{a,b,c,d,e,f},或者更大的集合,怎么写一个通用的(即元素数不限定在6)、可选出所有子集的算法,望赐教!
...全文
109 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
renheihei 2004-07-24
  • 打赏
  • 举报
回复
to kaphoon(齐柏林飞艇)
这是个排列算法!
ekschencn 2004-07-24
  • 打赏
  • 举报
回复
跟这个贴有点类似,楼主看看有帮助否:
http://community.csdn.net/Expert/topic/3188/3188630.xml?temp=.756222
lb2261981 2004-07-24
  • 打赏
  • 举报
回复
用STL库里的集合set
antijpn 2004-07-23
  • 打赏
  • 举报
回复
利用自然数的有序性,对元素的下标进行组合,最后只要通过下标访问元素即可。代码如下
unsigned int Combination(unsigned int const uiElemCount,unsigned int const CombCount)
{
unsigned int const ElemCount=uiElemCount-1;
unsigned int *const result=new unsigned int[CombCount];
unsigned int i,j,uiCount;

if(uiElemCount<CombCount || CombCount<1)
{
std::cout<<"NULL!\n";
return 1;
}

uiCount=0;
for(i=0;i<CombCount;i++)
result[i]=i; //初始化一个合适的数组
result[CombCount-1]--;

for(i=CombCount-1;;NULL)
{
if((ElemCount==result[0]+(CombCount-1)) && (ElemCount==result[CombCount-1]))
break;
if(ElemCount==result[i]+(CombCount-1)-i)//若result[i]于其倒序位置之和等于uiElemCount-1,则上一位应当被增加
{
result[i]=0;
i--;
continue;
}
else//否则这一位应该增加,并且应指向下一位
{
if((result[i]<result[i-1]) && i)
{
result[i]=result[i-1];
}
if(i!=CombCount-1)//如果不是正指向最后一位,则指向下一位
{
result[i]++;
//result[i+1]=result[i]+1;
i++;
continue;
}
else//否则自增
{
result[i]++;
}
}
for(j=0;j<CombCount;j++)
{
std::cout<<result[j]<<' ';
}
std::cout<<'\n';
uiCount++;
}
return uiCount;
}

不递归,这个版本的只是输出下标,想要输出排序的元素自己修改,核心部分已经注释
renheihei 2004-07-23
  • 打赏
  • 举报
回复
to 楼上:
神奇!algorithm,标准c++?
kaphoon 2004-07-23
  • 打赏
  • 举报
回复
#include<algorithm>
#include<iterator>
#include<iostream>
#include<set>
#include<string>
#include<ctime>
using namespace std;
int main()
{
clock_t start,end;
start = clock();
char array[]="abcdefg";
set<string> myset;
while(next_permutation(array,array+7))
{
for(int i=1;i <= 7;++i)
myset.insert(string(array,i));
}
copy(myset.begin(),myset.end(),ostream_iterator<string>(cout,"\n"));
end = clock();
cout<<(end-start)/CLOCKS_PER_SEC<<"seconds"<<endl;
}
renheihei 2004-07-23
  • 打赏
  • 举报
回复
如果共有n个元素
则i从0开始累加1,直到2的n次方结束
也就是说i的范围为0到(2^n - 1)
那么所有在这个范围内的正数,其最末n个bit的组合
正是此集合的各子集
譬如楼主的例子,n=3
当i为3的时候,其最末3位bit为011,那么a对应0(去除),b和c各对应1,保留,所以{b,c}即为其中一个子集

当S = <a,b,c>时,n = 3,(看二进制的后n位)

1 = 1 -->末3位 001 -->对应集合 <c>
2 = 10 -->末3位 010 -->对应集合 <b>
3 = 11 -->末3位 011 -->对应集合 <b,c>
4 = 100 -->末3位 100 -->对应集合 <a>
5 = 101 -->末3位 101 -->对应集合 <a,c>
6 = 110 -->末3位 110 -->对应集合 <a,b>
7 = 111 -->末3位 111 -->对应集合 <a,b,c>
8 = 1000 -->末3位 000 -->对应集合 <>

设<a,b,c>中a,b,c的序号分别为3,2,1,则a对应2*2*2=(100),b对应2*2=(010),c对应2=(001)
用(100),(010),(001)分别与上面的8种情况做&(位与)运算,对应位为1的,表示该元素存在

例如上面第5种情况:

--(101)&(100) = 100 (a不存在)
|
--(101)&(010) = 000 (b不存在)
|
--(101)&(001) = 001 (c存在)
]]>.....
.....
BluntBlade 2004-07-23
  • 打赏
  • 举报
回复
组合算法罢了。去GOOGLE一下就有了。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧