首页 > 技术文章 > 递归之全排列问题

cxmhy 2015-04-28 22:10 原文

一、问题描述

如输入一个字符串abc,其中的元素都不一样,则根据数学知识很容易得知道它的全排列有n!=3!=6;

即abc;acb;bac;bca;cab;cba;

当然如果包含重复元素,如aab,实际的全排列是:aab;aba;baa三种,则需要剔除掉重复的情况。

这里我们就是研究如何准确无误的将其所有的排列进行统计以及显示等。

 

二、问题分析

对全排列问题而言,其过程可以理解为递归思想。如abc,我们先任意取一个元素如a,则对bc进行全排列,依次类推

直到最后只有一个元素全排列,即是它本身。

 

三、程序设计

#include<iostream>
#include<string>
#include<vector>                      //一种顺序容器
#include<algorithm>                 //含有泛型算法


using namespace std;


int num=0;

vector<string> output;               //存储string 对象的向量容器


void perm(string list,int k,int m)
{
         if(k==m)                          //表示一次全排列完成,则把这个字符数组赋值到string对象中
           {
                 if(find(output.begin(),output.end(),list)==output.end())  //如果要压入的string对象在vector中没有出现,则进行插入操作,否则,不进行添加

                 {

                        num++;                                 //数目加1
                        output.push_back(list);            //压入容器中

                 }
             }

          else
                for(int i=k;i<=m;i++)
               {
                        swap(list[k],list[i]);                  //将下标i和首元素的下标k调换
                        perm(list,k+1,m);                    //递归算法k+1-m的元素进行全排列
                        swap(list[k],list[i]);                  //保证每一层的元素不会发生变化,重新调换回来
               }

}

void main()
{
        string input;

        cout<<"Please input the string:"<<endl;
        cin>>input;

        perm(input,0,input.size()-1);                     //从下标0开始,实际是将这个string对象所有元素进行排列

        sort(output.begin(),output.end());             //对向量容器里的全排列进行字典排序,保证按照一定的顺序显示出来

        cout<<"全排列的数目是:"<<num<<endl;

 

        for(int i=0;i<output.size();i++)                 //显示操作
               cout<<output[i]<<'\t';

        while(1);
}

 

四、程序结果

推荐阅读