热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c语言输出数组的全排列组合,定义一个数组,编程打印它的全排列

定义一个数组,编程打印它的全排列。比如定义:#defineN3inta[N]{1,2,3};则运行结果是:$.a.out123132213

定义一个数组,编程打印它的全排列。比如定义:

#define N 3

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

则运行结果是:

$ ./a.out

1 2 3

1 3 2

2 1 3

2 3 1

3 2 1

3 1 2

1 2 3

程序的主要思路是:

把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数2和3做全排列。

把第2个数换到最前面来,准备打印2xx,再对后两个数1和3做全排列。

把第3个数换到最前面来,准备打印3xx,再对后两个数1和2做全排列。

可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题

解题过程:

(1) 当 N = 1的时候,则直接打印数列即可。

(2) 当 N = 2的时候,设数组为 [1, 2]

打印a[0], a[1] (即1,2)

交换a[0],a[1]里面的内容

打印a[0],a[1]   (此时已变成了 [2, 1] )

(3) 当 N = 3的时候,数组为 [1, 2, 3]

a.把1放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印2,3的全排列(即a[1], a[2]的全排列)

1  2  3

1  3  2b.  把2放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印1, 3的全排列

2   1  3

2   3  1

打印完后再换回原来的位置,即1还是恢复到a[0],2还恢复到a[1]的位置

c.把3放在a[0]的位置 (这时候需要交换的是原数组的a[0]和a[2]),然后打印1, 2的全排列

3   2  1

3   1  2

打印完后再换回原来的位置,即1还是恢复到a[0],3还恢复到a[2]的位置,

至此全排列完成

(4)N = 4, 5, 6....的思路与此相同

点击(此处)折叠或打开

#include

#define N 3

int a[N];

void perm(int); /*求数组的全排列 */

void print();

void swap(int, int);//交换前缀

int main(){

int i;

for(i = 0; i

a[i] = i + 1;

}

perm(0);

}

void perm(int offset){

int i, temp;

if(offset == N-1){

print();

return;

}else{

for(i = offset;i

swap(i, offset);//交换前缀

perm(offset + 1);//递归

swap(i, offset);//将前缀换回来,继续做前一次排列

}

}

}

void print(){

int i;

for(i = 0; i

printf(" %d ",a[i]);

printf("/n");

}

void swap(int i, int offset){

int temp;

temp = a[offset];

a[offset] = a[i];

a[i] = temp;

}

完成了上述要求之后再考虑第二个问题:如果再定义一个常量M表示从N个数中取几个数做排列(N == M时表示全排列),原来的程序照如下方式修改:

点击(此处)折叠或打开

#include

#include

#define N 4

#define M 3

int a[N]; /* N个数 */

int temp[M]; /* 从N个数中选出的M个数 */

void perm(int, int); /* 排列 */

void swap(int, int); /* 交换两个数 */

void print(); /* 打印 */

int main(){

int i;

int start = 0;//起始位置

int count = M;//排列到个数

for(i = 0; i

a[i] = i + 1;

}

perm(start, count);

}

void perm(int offset, int count){

int i;

if( count == 0 ){

print();

return;

}else{

for(i = offset; i

temp[offset] = a[i];

swap(offset, i);

perm(offset+1, count-1);

swap(offset, i);

}

}

}

void swap (int offset, int i){

int another;

another = a[offset];

a[offset] = a[i];

a[i] = another;

}

void print(){

int i;

for(i = 0; i

printf(" %d ",temp[i]);

printf("/n");

}

最后再考虑第三个问题:从N个数中取M个数做组合,

先看一个例子:

C(5,3) = 10

1 2 3

1 2 4

1 2 5

1 3 4

1 3 5

1 4 5

2 3 4

2 3 5

2 4 5

3 4 5

分析

1 | 2 3

1 | 2 4

1 | 2 5

1 | 3 4

1 | 3 5

1 | 4 5

------ C(4, 2)∵可以在{2, 3, 4, 5}中挑2个出来。

2 | 3 4

2 | 3 5

2 | 4 5

------ C(3, 2)∵可以在{3, 4, 5}中挑2个出来。

3 | 4 5

------ C(2, 2)∵只能在{4, 5}中挑2个出来。

这样就很容易写出递归算法来:

点击(此处)折叠或打开

Algorithm combination(n, k, A[l..n+l-1])

if k = 0

print ary[1..k]

else

for i←1 to n-k+1

ary[index++] = A[l+i-1]

combination(n-i, k-1, A[l+i..n+l-1])

--index

endfor

源代码如下:

点击(此处)折叠或打开

#include

#include

#define N 4

#define M 3

int a[N]; /* N个数 */

int temp[M]; /* 从N个数中选出的M个数 */

int top;

void comb(int, int); /* 组合 */

void swap(int, int); /* 交换两个数 */

void print(); /* 打印 */

int main(){

int i;

int start = 0;//起始位置

int count = M;//排列到个数

for(i = 0; i

a[i] = i + 1;

}

comb(start, count);

}

void comb(int offset, int count){

int i;

if( count == 0 ){

print();

return;

}else{

for(i = offset; i

temp[top++] = a[i];

comb(i+1, count-1);

--top;

}

}

}

void print(){

int i;

for(i = 0; i

printf(" %d ",temp[i]);

printf("/n");

}



推荐阅读
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了C++中的引用运算符及其应用。引用运算符是一种将变量定义为另一个变量的引用变量的方式,在改变其中一个变量时,两者均会同步变化。引用变量来源于数学,在计算机语言中用于储存计算结果或表示值抽象概念。变量可以通过变量名访问,在指令式语言中引用变量通常是可变的,但在纯函数式语言中可能是不可变的。本文还介绍了引用变量的示例及验证,以及引用变量在函数形参中的应用。当定义的函数使用引用型形参时,函数调用时形参的改变会同时带来实参的改变。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
author-avatar
大大炮
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有