免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9092 | 回复: 16
打印 上一主题 下一主题

无聊就进来看看:关于排列数字的所有可能组合 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-05 12:44 |只看该作者 |倒序浏览
因为需要写一个排列数字的所有可能组合,于是我开始思考:

比如给出1至4四个数字

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

那么写出他们的所有可能的组合为:

4 3 2 1        4 3 1 2        4 2 3 1        4 2 1 3        4 1 3 2        4 1 2 3        3 4 2 1        3 4 1 2
3 2 4 1        3 2 1 4        3 1 4 2        3 1 2 4        2 4 3 1        2 4 1 3        2 3 4 1        2 3 1 4
2 1 4 3        2 1 3 4        1 4 3 2        1 4 2 3        1 3 4 2        1 3 2 4        1 2 4 3        1 2 3 4

共4*3*2*1=24组,看来是个阶乘,那么是不是可以for (int i=0;i<24;i++)?

显然不可以。那么写个阶乘的递归吧!可是….可是…..努力了半天之后发现我做不到!!!

哪位大大可以帮帮忙把它写出来让我看看啊???

我得想想其他办法!于是我想到了寻路问题,好像叫图…翻了一下书,嗯!确实有这么一种。又半天时间,终于搞定了,但是…

排列出来的数字好像不怎么”规矩”……

再经过整整一整天的努力,呼~~~~~~~
搞定了,世界清净了。

我高兴得像个孩子般乱跳,可跳完之后我又不高兴了:“整整两天啊!!!!我适合做这行吗???
谁能告诉我???我需要别人的意见!!!

我发现递归虽然很有用,但不好理解(当然也就不容易用),特别是和循环在一起的时候,谁能说一说用的时候要从哪下手?有什么技巧?

呵呵,罗嗦了这么多,大家练练手吧!排列数字的所有可能组合
要有人感兴趣,过两天我把我的贴出来!没人感兴趣?那算了。

另:财产已冻结兄弟的"算大数(比如100)阶乘的思路"有时间我会仔细看看的。

论坛徽章:
0
2 [报告]
发表于 2006-01-05 13:07 |只看该作者
《数据结构、算法与应用》中有个递归的实现方法例子

论坛徽章:
0
3 [报告]
发表于 2006-01-05 15:42 |只看该作者
原帖由 fansfamily 于 2006-1-5 12:44 发表
因为需要写一个排列数字的所有可能组合,于是我开始思考:

比如给出1至4四个数字

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

那么写出他们的所有可能的组合为:

4 3 2 1        4 3 1 2        4 2 3 1        4 2 1 3        4 1 3 2        4 1 2 3        3 ...



打印出所有4位数的组合,然后去除掉了所有相同数字的组合.

论坛徽章:
0
4 [报告]
发表于 2006-01-05 16:18 |只看该作者

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <alloc.h>
  4. int UpLimit;
  5. int *Array;
  6. int checkArray();
  7. void printArray();
  8. main()
  9. {
  10.         int i,Index;
  11.         printf("Please let me know the N:");
  12.         scanf("%d",&UpLimit);
  13.         Array=(int *) calloc(UpLimit,sizeof(int));
  14.         for (i=1;i<UpLimit;i++) Array[i]=0;
  15.         while (Array[UpLimit-1]<=UpLimit)
  16.         {
  17.                 Array[0]++;
  18.                 if (Array[0]<=UpLimit)
  19.                 {
  20.                         if (checkArray()) printArray();
  21.                         continue;
  22.                 }
  23.                 Array[0]=0;
  24.                 Index=1;
  25.                 while (Index<UpLimit)
  26.                 {
  27.                         Array[Index]++;
  28.                         if (Array[Index]<UpLimit+1) break;
  29.                         Array[Index]=0;
  30.                         Index++;
  31.                 }
  32.                 if (Index>=UpLimit) break;
  33.         }
  34.         free(Array);
  35.         return 0;
  36. }

  37. int checkArray()
  38. {
  39.         int i,j;
  40.         for (i=0;i<UpLimit-1;i++)
  41.         {
  42.                 if (Array[i]==0) return 0;
  43.                 for (j=i+1;j<UpLimit;j++) if (Array[i]==Array[j] || Array[j]==0) return 0;
  44.         }
  45.         return 1;
  46. }

  47. void printArray()
  48. {
  49.         int i;
  50.         for(i=0;i<UpLimit;i++) printf("%3d ",Array[i]);
  51.         printf("\n");
  52. }
复制代码

论坛徽章:
0
5 [报告]
发表于 2006-01-05 19:46 |只看该作者
写了个最简思维的.
  1. print_it()
  2. {
  3.         char sNum[5];
  4.         int i,j,k,l;
  5.         for(i=1;i<5;i++)
  6.         {
  7.                 for(j=1;j<5;j++)
  8.                 {
  9.                         if (j==i) continue;
  10.                         for(k=1;k<5;k++)
  11.                         {
  12.                                 if (k==j || k==i) continue;
  13.                                 for(l=1;l<5;l++)
  14.                                 {
  15.                                         if (l==k ||l==j ||l==i) continue;
  16.                                         printf("%d%d%d%d\n",i,j,k,l);
  17.                                 }
  18.                         }
  19.                 }
  20.         }
  21. }
复制代码

[ 本帖最后由 zhhui2000 于 2006-1-5 19:51 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-01-05 19:52 |只看该作者

论坛徽章:
0
7 [报告]
发表于 2006-01-07 19:08 |只看该作者

回复:

首先谢谢所有回帖的朋友!谢谢!!!

2楼-daviescai:

不管如何,谢谢!

《数据结构、算法与应用》中有个递归的实现方法例子

是否就是排列数字的所有可能组合?

如果只是单纯的递归例子――我想可能是我的语言表达有问题,我并不是不会用递归,只是我在解这道题时,像五楼的答案,我想把它以递归的形式实现,以便能接收任意多个数字。但是该怎样实现?从哪入手?我不知道!因此寻求别人的帮助。

3楼-mik

我并没有丝毫对你有意见的意思,但是――想的比说的容易,说的比做的简单。

即使打印出所有N位数的组合,但去除掉了所有相同数字的组合是很费时的,同意吗?

4楼-RobinHoo:

果然是骑士!我很佩服你,这么短的时间内就找到办法解决了问题。

你的实现我仔细看了,是通过不断比较,不断进位达到目的的!这确是一种很好的思路。看得出是你自己想出来的。向你致敬!

不足的是每次都要查找比较,且进位慢(要等前面所有位填充满),所以也比较费时,相信你也察觉到了。
我找了个大于10的数字试试^_^:!把我的CPU累个半死!且排列出的数字不”规矩”。

建议看看六楼win_hate ( @v@)的方案。

同时想问一下,你运行的环境是什么?恐怕不是window吧!我用的是VS.net,可是编译时提示找不到alloc.h,找到了也有一大堆问题,改用WinGW也一样。

五楼-zhhui2000:

我只能说确实是最简单的思维:!人为干预的痕迹太重了,如果我想排列10个数字的所有组合呢?呵呵~~~让你费心了,试试能否把它用递归的形式实现。

六楼-win_hate ( @v@):

不愧为版主,原来这题早有人研究过了!
不过两个方案中都有个明显的问题:(2) 假定 1, 2, ..., k 的 k! 个排列 P(k) 已经给定,考虑 P(k+1).如果我想排列10个数字的所有组合,那么首先要把前面九个全部排列出来……并且排列出的数字不”规矩”。

不得不承认,两种方案都是很巧妙的方法,有些异曲同工。想出方案的人肯定对这很有研究。在下对此佩服得五体投地,自愧不如!

接下来是我的实现结果。

me.rar

1.38 KB, 下载次数: 123

源文件

论坛徽章:
0
8 [报告]
发表于 2006-01-07 19:09 |只看该作者

首先是失败的例子:


  1. void run_sort(int inow,int icount,int isize)
  2. {
  3.         int iTemp = isize - inow;
  4.         if (icount < inow)
  5.         {
  6.                 int iValue = iTable[iTemp + icount];
  7.         //        if (iValue == iTable[iTemp] && iTemp + icount + 1 < isize)
  8.                 if (icount != 0 | inow == 1)
  9.                 {
  10.                         for (int i=0;i<iTemp;i++)
  11.                         {
  12.                                 cout<<iTable[i];
  13.                         }
  14.                         cout<<iValue;
  15.                         for (int i=iTemp;i<isize;i++)
  16.                         {
  17.                                 if (iTable[i] != iValue)
  18.                                 {
  19.                                         cout<<iTable[i];
  20.                                 }
  21.                         }
  22.                         cout<<"\t";
  23.                 }
  24.                 icount++;
  25.         }
  26.         if (icount >= inow)
  27.         {
  28.                 icount = 0;
  29.                 inow++;
  30.         }
  31.         iTemp = isize - inow;
  32.         if (inow < isize)
  33.         {
  34.                 run_sort(inow,icount,isize);
  35.         }
  36. }
复制代码

思路是通过替换每位数,后来搞混了,有些乱七八糟了。

论坛徽章:
0
9 [报告]
发表于 2006-01-07 19:11 |只看该作者

然后是寻路实现:

好像还有个名堂,叫深度(还是广度?)优先搜索。

  1. #include <fstream>
  2. #include <iostream>
  3. #include <time.h>
  4. using namespace std;
  5. int **imap;
  6. int *path;
  7. bool *bselected;                //当前数字是否已排上
  8. int *iTable;
  9. int iselected = 0,ibeg = 0,iend = 0,isize = 0;
  10. void Init_Table(int isize)
  11. {
  12.         iTable = new int[isize];
  13.         for (int i=0;i<isize;i++)
  14.         {
  15.                 iTable[i] = i+1;
  16.         }
  17. }
  18. void Init_Map(int isize)
  19. {
  20.         Init_Table(isize);
  21.         imap = new int*[isize];
  22.         path = new int[isize];
  23.         bselected = new bool[isize];
  24.         for (int i=0;i<isize;i++)
  25.         {
  26.                 imap[i] = new int[isize];
  27.                 bselected[i] = false;
  28.                 for (int j=0;j<isize;j++)
  29.                 {
  30.                         if (i == j)
  31.                         {
  32.                                 imap[i][j] = 0;
  33.                         }
  34.                         else
  35.                         {
  36.                                 imap[i][j] = 1;
  37.                         }
  38.                 }
  39.         }
  40. }
  41. void run_B(const int inow)
  42. {
  43.         for (int i=0;i<isize;i++)
  44.         {
  45.                 if (imap[inow][i] == 1 && bselected[i] == false)                //可行且未排过
  46.                 {
  47.                         path[iselected] = iTable[i];
  48.                         bselected[inow] = true;
  49.                         iselected++;
  50.                         if (iTable[i] == iend)                //到达目标
  51.                         {
  52.                                 if (iselected + 1 == isize)                //是否差一个数字就全都排上
  53.                                 {
  54.                                         cout<<ibeg;
  55.                                         for (int j=0;j<isize-1;j++)
  56.                                         {
  57.                                                 cout<<path[j];
  58.                                         }
  59.                                         cout<<"\t";
  60.                                 }
  61.                                 else
  62.                                 {
  63.                                         iselected--;
  64.                                         bselected[inow] = false;
  65.                                         continue;
  66.                                 }
  67.                         }
  68.                         else
  69.                         {
  70.                                 run_B(i);
  71.                         }
  72.                         iselected--;
  73.                         bselected[inow] = false;
  74.                 }
  75.         }
  76. }
  77. void B(int isize)
  78. {
  79.         Init_Map(isize);
  80.         for (int i=0;i<isize;i++)
  81.         {
  82.                 for (int j=0;j<isize;j++)
  83.                 {
  84.                         if (iTable[i] != iTable[j])
  85.                         {
  86.                                 ibeg = iTable[i];
  87.                                 iend = iTable[j];
  88.                                 iselected = 0;
  89.                                 run_B(i);
  90.                         }
  91.                 }
  92.         }
  93. }
  94. void run_main()
  95. {
  96.         cout<<"Please let me know the N:";
  97.         cin>>isize;
  98. //        clock_t iTime = clock();
  99.         B(isize);
  100. //        cout<<"\n" <<clock() - iTime <<"\n";
  101. }
  102. int main()
  103. {
  104.         run_main();
  105.         system("pause");
  106. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2006-01-07 19:12 |只看该作者

本来到此就该结束了,可是...

可是,虽然结果也有一定的规律可寻,但我要的不止是这样。我又得想别的办法。想来想去,觉得失败的第一种也不是不可取……

  1. #include <fstream>
  2. #include <iostream>
  3. #include <time.h>
  4. using namespace std;
  5. int *iTable;
  6. int isize = 0;

  7. struct doubleLink
  8. {
  9.         int iValue;
  10.         doubleLink *pLast;
  11.         doubleLink *pNext;
  12. }dbLink;
  13. doubleLink *istack;
  14. void Init_doubleLink(int isize,doubleLink *dbLink)
  15. {
  16.         Init_Table(isize);
  17.         if (!dbLink)
  18.                 dbLink = new doubleLink;
  19.         doubleLink *pNext = dbLink,*pLast;
  20.         dbLink->pLast = NULL;
  21.         for (int i=1;i<isize;i++)
  22.         {
  23.                 pNext->iValue = i;
  24.                 pNext->pNext = new doubleLink;
  25.                 pLast = pNext;
  26.                 pNext = pNext->pNext;
  27.                 pNext->pLast = pLast;
  28.         }
  29.         pNext->iValue = isize;
  30.         pNext->pLast = pLast;
  31.         pNext->pNext = NULL;
  32. }
  33. void stack_add(const int iValue)
  34. {
  35.         if (!istack)
  36.         {
  37.                 istack = new doubleLink;
  38.                 istack->iValue = iValue;
  39.                 istack->pLast = NULL;
  40.                 istack->pNext = NULL;
  41.                 return;
  42.         }
  43.         doubleLink *pNext = istack,*pLast = NULL;
  44.         int isFind = false;
  45.         while(pNext)
  46.         {
  47.                 if(pNext->iValue == iValue)
  48.                 {
  49.                         isFind = true;
  50.                 }
  51.                 pLast = pNext;
  52.                 pNext = pNext->pNext;
  53.         }
  54.         if (!isFind)
  55.         {
  56.                 pNext = new doubleLink;
  57.                 pNext->iValue = iValue;
  58.                 pNext->pLast = pLast;
  59.                 pNext->pNext = NULL;
  60.                 if (pLast)
  61.                         pLast->pNext = pNext;
  62.         }
  63. }
  64. void stack_del(const int iValue)
  65. {
  66.         doubleLink *pNext = istack,*pLast = NULL;
  67.         while(pNext)
  68.         {
  69.                 if(pNext->iValue == iValue)
  70.                 {
  71.                         if (!pNext->pNext)
  72.                         {
  73.                                 delete[] pNext;
  74.                                 pNext = NULL;
  75.                                 if (pLast)
  76.                                 {
  77.                                         pLast->pNext = NULL;
  78.                                 }
  79.                                 else
  80.                                 {
  81.                                         istack = NULL;
  82.                                 }
  83.                         }
  84.                         else
  85.                         {
  86.                                 pLast->pNext = pNext->pNext;
  87.                                 pNext->pNext->pLast = pLast;
  88.                                 delete[] pNext;
  89.                                 pNext = NULL;
  90.                         }
  91.                         break;
  92.                 }
  93.                 pLast = pNext;
  94.                 pNext = pNext->pNext;
  95.         }
  96. }
  97. bool stack_find(const int iValue)
  98. {
  99.         doubleLink *pNext = istack;
  100.         while(pNext)
  101.         {
  102.                 if(pNext->iValue == iValue)
  103.                 {
  104.                         return true;
  105.                 }
  106.                 pNext = pNext->pNext;
  107.         }
  108.         return false;
  109. }
  110. int icount = 0;
  111. doubleLink *pTemp;
  112. void run_A(int inow = 0)
  113. {
  114.         for (int i=inow;i<isize;i++)
  115.         {
  116.                 if (!stack_find(iTable[i]))
  117.                 {
  118.                         if (icount == isize)
  119.                         {
  120.                                 icount = 0;
  121.                                 pTemp = istack;
  122.                                 while (pTemp)
  123.                                 {
  124.                                         icount++;
  125.                                         cout<<pTemp->iValue;
  126.                                         pTemp = pTemp->pNext;
  127.                                 }
  128.                         }
  129.                         icount++;
  130.                         cout<<iTable[i];
  131.                         stack_add(iTable[i]);
  132.                         run_A(inow);
  133.                         stack_del(iTable[i]);
  134.                 }
  135.         }
  136.         cout<<"\t";
  137. }
  138. void A(int isize)
  139. {
  140.         Init_doubleLink(isize,istack);
  141.         run_A();
  142. }
  143. void run_main()
  144. {
  145.         cout<<"Please let me know the N:";
  146.         cin>>isize;
  147. //        clock_t iTime = clock();
  148.         A(isize);
  149. //        cout<<"\n" <<clock() - iTime <<"\n";
  150. }
  151. int main()
  152. {
  153.         run_main();
  154.         system("pause");
  155. }
复制代码

看出来了吗?已排过的数字入堆,剩下的就是排列未入堆的数字,排完就出来。至于为什么是双链表,而不是单链表或数组?那是因为我至今还没实现过双链表,想实现看看^_^。

呼!终于搞定!历时……一个下午!!!挺不容易的,如有不当之处,希望大家看在我这么辛苦,这么诚心的诚意上,就算啦~~~~原谅…原谅…
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP