排列组合,n个元素中选m个元素进行排列组合,组合算法和排列算法综合,c++实现

本文介绍了排列与组合的基本概念及计算公式,并通过示例讲解了如何利用组合算法与全排列算法实现从n个元素中选取m个元素的所有可能组合与排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

知识储备

1.排列

        排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示

                   计算公式:

注意:m中取n个数,按照一定顺序排列出来,排列是有顺序的,就算已经出现过一次的几个数。只要顺序不同,就能得出一个排列的组合,例如1,2,3和1,3,2是两个组合。

2.组合

组合的定义:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。

                    计算公式:

注意:m中取n个数,将他们组合在一起,并且顺序不用管,1,2,3和1,3,2其实是一个组合。只要组合里面数不同即可
 

学习组合算法:https://blog.csdn.net/huang1600301017/article/details/88769270

学习全排列算法:https://mp.csdn.net/postedit/88770980

建议先学习以上两个算法再学习这篇博客

组合算法是找出不同的组合序列,全排列算法是对一组序列按照一定顺序进行排列。

从n个元素中选m个元素进行排列组合,就是组合算法+全排列算法。即先在n个元素中用组合算法找出不同的组合,再用全排列算法对选出来的组合进行全排列。

例如:1,2,3,4,5,5个元素选出3个进行排列组合,共有

1 2 3
1 2 4
1 3 4
2 3 4
1 2 5
1 3 5
2 3 5
1 4 5
2 4 5
3 4 5
10种组合,再对上面每一小组组合进行全排列,所有的组合不就是排列组合的结果吗。共有60种。

代码:

#include <iostream>
using namespace std;
void Show(int ,int ,int index[],int value[]);  //组合算法系列、排列算法系列
bool judge(int,int ,int index[]);  //组合算法系列
void change(int ,int ,int index[],int value[]);  //组合算法系列
void Perm(int ,int ,int arr[]); //排列算法系列
int perm_number = 0;
int main()
{

    int i,n,m;
    cout<<"请输入元素个数:";
    cin>>n;
    cout<<"请输入选多少元素:";
    cin>>m;
    int index[n]={0},value[n]; //index务必初始化为0,不然无法知道m个数之后里面是真还是假
    for(i=0;i<n;i++)
    {
        value[i]=i+1;//此处是赋初值,以1,2,3,4,5为例,当然任何数字都可以
    }
    change(n,m,index,value);
    cout<<"共有"<<perm_number<<"种排列组合"<<endl;
    return 0;
}

void Show(int n,int m,int index[],int value[])
{
    int i,count=0;
    int arr[m];
    for(i=0;i<n;i++)
    {
        if(index[i])
        {
            arr[count++]=value[i];   //将选出来的组合赋值给一个数组,为全排列做准备
        }
    }
    //已经有组合出来了,开始进行全排列
    Perm(0,m,arr);
}

bool judge(int n,int m,int index[])
{
    int i;
    for(i=n-1;i>=n-m;i--)
    {
        if(!index[i])  return false;
    }
    return true;
}

void change(int n,int m,int index[],int value[])  //核心算法函数
{
    int i,j,num=0;
    for(i=0;i<m;i++)
    {
        index[i]=1;
    }
    Show(n,m,index,value); //第一个组合
    num +=1;
    while(!judge(n,m,index))  //只要没使1全部移到右边,就继续循环
    {
        for(i=0;i<n-1;i++)  //注意是n-1,因为i=n-1时,i+1是不存在的
        {
            //找到10,变成01
            if(index[i]==1&&index[i+1]==0)
            {
                index[i]=0;
                index[i+1]=1;
                //将01组合左边的1全部放在数组最左边
                int count=0;
                for(j=0;j<i;j++)
                {
                    if(index[j])
                    {
                        index[j]=0;
                        index[count++]=1;
                    }
                }
                Show(n,m,index,value);  //输出
                num +=1;
                break;
            }
        }
    }
    cout<<"共有"<<num<<"种组合"<<endl;
}

//全排列算法
void Perm(int start,int end,int arr[]) //这里相当于递归算法,
{
    //道理start=end时,就相当于这次递归结束,找到了一个排列组合
    if(start == end)
    {
        for(int i=0;i<end;i++)
        {
            cout<<arr[i]<<" ";
        }
        cout<<endl;
        perm_number +=1;
        return ;
    }
    for(int i=start;i<end;i++)
    {
        swap(arr[start],arr[i]);//假设3,4,5为例,3P(4,5)是已经一个组合,后面则是4P(3,5),5P(3,4),因此需要交换一下
        Perm(start+1,end,arr);//相当于P(4,5)
        swap(arr[i],arr[start]);//回溯,把顺序还原,不然就破坏了数据,排列就进行不下去了
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值