Chinaunix首页 | 论坛 | 博客
  • 博客访问: 219692
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-09 10:55
个人简介

每天改变一点点,生活充满了惊喜。

文章分类

全部博文(42)

文章存档

2016年(8)

2015年(29)

2014年(5)

我的朋友

分类: C/C++

2015-04-20 14:28:29

前面总结完位图解法,直到最近才有时间,继续对求子集的方法做一个整理。
回溯法有两种思路:
(1)第一种是将子集保存在一个字符数组中,每次往数组中移入一个元素,
从空集增加到最大集,再回溯,递归返回的时候,再将最后的元素从子集移出,
这样就实现了,元素在与不在子集中,这两种状态。
注意,每次加入一个元素得到的,子集数组中的元素就构成了一个子集。

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. void get_sub_set(char *start, char *end, char *str);

  4. /**
  5.  * @PARAM start表示还未添加到子集中的元素的开始位置
  6.  * @PARAM end表示集合最后一个元素的位置
  7. */
  8. void get_sub_set(char *start, char *end, char *str)
  9. {
  10.     char *p = start;
  11.     int len = strlen(str);
  12.     while (p <= end) /*向子集中依次添加未放入子集中的元素,一次一个*/
  13.     {
  14.         str[len] = *p; /*子集中添加一个未放入子集的元素。*/
  15.         str[len + 1] = 0;
  16.         printf("%s \n",str);
  17.         p++;
  18.         get_sub_set(p, end, str); /* 把集合中的所有元素都加入子集中 */
  19.         str[len] = 0; /* 递归返回的过程中,删除最后一个元素 */
  20.     }
  21. }

  22. int main()
  23. {
  24.     //char set[] = "0123456789abcdefghij";
  25.     char set[] = "012";
  26.     int set_elem_count = strlen(set);
  27.     char sub_list[set_elem_count];
  28.     memset(sub_list,'\0', set_elem_count * sizeof(char));
  29.     printf("%s \n",sub_list); // 初始时子集string为空集
  30.     get_sub_set(set, &set[set_elem_count - 1], sub_list);

  31.     return 0;
  32. }
程序输出为:


如果集合字符串为"0123456789abcdefghij" ,20个字符,算法的执行时间为15s左右(当然这个是跟机器的处理能力有很大关系的)。

(2)第二种思路还是从元素在与不在子集这两种状态来考虑,因为每个元素都有两种状态,
可以理解为一种二叉树的形式,如下图:


每一个元素带有一个属性,在不在子集中,1表示在子集,0表示不再自己中。
每个元素的状态初始化为1,实际上无需去构造二叉树。
第一个递归将所有元素逐个放入子集,当所有元素放入子集后回溯,
第一次递归返回后,将最后一个元素移出子集,这样每个元素在与不在子集的状态都可以遍历到,
每次遍历到最后一个元素时,按照元素的状态打印字符序列,得到的就是一个子集,
参考上图就是每次遍历到c字符就打印子集,按照每一个a到c的路径,可以打印出所有的子集。

  1. #include <stdio.h>
  2. #define MAX_NUM 50

  3. enum boolean {true=1,false=0};
  4. typedef enum boolean bool;

  5. void get_sub_set(bool * visit, char * set , int cur, int count);

  6. void get_sub_set(bool * visit, char * set , int cur, int count)
  7. {
  8.     if ( set[cur] == '\0') {
  9.         int i = 0;
  10.         for (; i < count; ++i){
  11.             if ( visit[i] ) {
  12.                 printf("%c ",set[i]);
  13.             }

  14.         }
  15.         printf("\n");
  16.         return;
  17.     }
  18.     visit[cur] = true;
  19.     get_sub_set(visit, set, cur + 1, count);
  20.     visit[cur] = false;
  21.     get_sub_set(visit, set, cur + 1, count);
  22. }

  23. int main()
  24. {
  25. // char set[MAX_NUM] = "0123456789abcdefghij";
  26.     char set[MAX_NUM] = "012";
  27.     int count = 0;
  28.     while ( set[count] != '\0' ){
  29.         count ++;
  30.     }
  31.     
  32.     bool visit[count];
  33.     int i = 1;
  34.     for (;i<=count;i++){
  35.         visit[i] = false;
  36.     }

  37.     get_sub_set(visit, set,0,count);
  38.     return 0;
  39. }
程序输出为:


如果集合字符串为"0123456789abcdefghij" ,20个字符,算法的执行时间为18s左右。



阅读(4812) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~