求集合的幂集

求集合的幂集,我总结了2种方法

1 这道题如果刚开始没有思路,可以考虑一下一个元素在不在子集中是有两种状态的,可以用什么表示呢?

如果用0表示不在,1表示在的话,就是01序列的2进制数。只需要遍历0-2的n次幂的二进制01序列就可以了

 

这个是我早期写的代码

 /*求一个集合的全部子集
  增广贤文
  2006.5.9
  */

int a[]={1,2,3,4};


#include <stdio.h>
#include <math.h>
#define N sizeof a/sizeof a[0]

 

void change(int b[])
{
 int *p=b;
 for(p=b;p<=b+N;p++)
 {
  if(*p==0)
   {
     *p=1;
     break;
    }
  else if(*p==1)
  {
    *p=0;

   }

 }

}

main()
{
  int i;
  int j;
  int b[N-1];


 for(i= 0;i<N;i++)
 b[i]=0; /*初始化数组b[i]*/

 printf("the original set is :/n");

 printf("{");
 for(i=0;i<N;i++)
 {
  printf("%d ",a[i]);
  }
 printf("}/n") ;

 

 printf("/n");
 printf("all the Subsets as follows:/n ") ;

 

 for(j=0;j<pow(2,N);j++)
 {
  printf("{");
  for(i=0;i<N;i++)
  {
   if(b[i]!=0)
   printf("%d ",a[i]);
   else
   printf(" ");

  }
  printf("}/n");
   change(b);

 }


 getch();
 }

 

 

 

2.使用二叉树遍历的方式

 //作者 :增广贤文
//时间:2006.9.23
//内容:运用二叉树求一个集合的幂集
//经过测试准确无误

#include <iostream>
using namespace std ;

typedef struct node
{
    char data ;
    struct node * next ;
}listnode , * list ;

void CreateList(list &A);//创建一个链表

void Output(list A);//打印一个链表

int ListLength(list A);//求一个链表的长度,返回链表的长度

void GetElem(list A , int i , char &x ) ;//求链表的第i个元素x

void ListInsert(list A , int i , char x);//在链表的第i个节点后插入元素

void ListDelete(list A ,int i , char x) ;//删除链表的第i个节点

void PowerSet(int i ,list A ,list B);//求链表A的幂集,链表B表示A幂集的一个元素


char x ;
int main()
{
    list A ;
    cout<<"请输入集合的元素 :" ;
   
    CreateList(A);
  
   
   
    list B;
    B = new listnode ;
    B->data = 0 ;
    B->next = NULL ;
    PowerSet(1,A,B);
   
   
   
    putchar('/n');
    system("PAUSE");
    return 0 ;
}  

void CreateList(list &A) //创建一个链表
{
     char value ;
     A = new listnode ;
     A->next = NULL ;
     A->data = 0 ;
    
     list p = NULL ;
     list q = NULL ;
    
     while((value = getchar())!= '/n')
     {
       
          if(A->next == NULL)
           {
              p = new listnode ;
              p->data = value ;
              A->next = p ;
              p->next = NULL ;
              A->data++ ;
           }
    
          else
          {
              q = new listnode ;
              q->data = value ;
              p->next = q ;
              p = q ;
              A->data++ ;
                       
          }
    
     }
    
     if(p != NULL)
     {
          p->next = NULL ;
      }
   
}   

void Output(list A)//打印一个链表
{
     if(ListLength(A) > 0)
     {
     list p ;
     p = A->next ;
     while( p != NULL)
     {
         cout<<p->data<<"  ";
         p = p->next ;
     }
    
     }
    
     else
     cout<<"空集";
   
}   

int ListLength(list A)//求一个链表的长度,返回链表的长度
{
    return (int)A->data ;
}

void GetElem(list A , int i , char &x ) //求链表的第i个元素x
{
   
     list p = A ;
     int num = 1 ;
     while(num < i+1)
     {
       p = p->next ;
       num++ ;
      }
     
      x = p->data;
}


void ListInsert(list A , int i , char x)// 将元素x插入,在链表第i个节点位置
{
   
     list p = A ;
     list q = new listnode ;
     q->data = x ;
     int num = 0 ; //头节点的编号是0 
     while(num < i-1)
     {
       p = p->next ;
       num++ ;
      }
     q->next = p->next ;
     p->next = q ;
     A->data++;
}

void ListDelete(list A ,int i , char x) //删除链表的第i个节点
{
  
     list p = A ;
  
     int num = 1 ;
     while(num < i)//循环的到的p是第i-1个节点
     {
       p = p->next ;
       num++ ;
      }
      list q = p->next ;//q为第i个节点
     
      p->next = q->next ;
      delete q ;
      A->data-- ;
    
}

void PowerSet(int i ,list A ,list B)//求链表A的幂集,链表B表示A幂集的一个元素
{
    
     if(i > ListLength(A))
     {
       Output(B);
       putchar('/n');
     }
     else
       {
           GetElem(A,i,x);
           int k = ListLength(B);     
           ListInsert(B,k+1,x);
           PowerSet(i+1,A,B);
           ListDelete(B,k+1,x);
           PowerSet(i+1,A,B);
        }
}
 

    

 

这个算法在清华大学的数据结构上有详细的解释



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1287932

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值