全排列问题(基于元素交换的算法的C++实现)

一、题目

生成1~n的全排列

二、解题思路

我们尝试用递归的思想解决:

  • 1与1交换,继续求子问题(2,3,...,n)的子问题。
  • 2与1交换,继续求子问题(1,3,...,n)的子问题。
  • 3与1交换,继续求子问题(2,1,...,n)的子问题。

................................

  • n与1交换,继续求子问题(2,3,...,1)的子问题。

这样每个数开头一次,递归求解剩下序列的排序,即可得到n个数的全排列。假如 我们有1,2,3,4,下面我们用上述思想生成1,2,3,4的全排列。

  • 首先,1与1交换,在继续求子问题(2,3,4),该子问题又分为三种子问题,一种是2和2交换,继续求子问题(3,4)接下来继续求子问题(3,4),一种是3和3交换,剩下子问题{4},单独元素,直接返回排列为(1,2,3,4),另一种是4和3交换,剩下子问题{3}, 单独元素,直接返回(1,2,4,3);另一个是3和2交换,继续求(2,4)的子问题,接下来继续求子问题(2,4),一种是2和2交换,剩下子问题{4},单独元素,直接返回排列为(1,3,2,4),另一种是4和2交换,剩下子问题{2}, 单独元素,直接返回(1,3,4,2);最后一种是4和2交换,继续求(3,2)的子问题,接下来继续求子问题(3,2),一种是3和3交换,剩下子问题{2},单独元素,直接返回排列为(1,4,3,2),另一种是3和2交换,剩下子问题{2}, 单独元素,直接返回(1,4,2,3)。
  • 2与1交换,继续求子问题(1,3,4)的子问题。略
  • 3与1交换,继续求子问题(2,1,4)的子问题。略
  • 4与1交换,继续求子问题(2,3,1)的子问题。略

三、代码编写 

#include <iostream>
#define N 100

using namespace std;

//保存待排列数组
int a[N] = {0};
//记录需要排列元素个数
int length = 0;
//交换数组的两个数,参数为数组索引
void swap(int s,int t){
    int temp = a[t];
    a[t] = a[s];
    a[s] = temp;
}
//index表示从第index开始,计算index到n的的全排列,
//即dfs(1)代表从第一数算起,生成1-n的全排列
void dfs(int index){
    if(index > length){
        for(int i = 1;i <= length ; i++){
            cout<<a[i]<<" ";
        }
        cout<<endl;
        return;
    }
    else{
        for(int i = index ; i <= length ;i++){
            swap(i,index);
            //继续生成index+1到n的全排列
            dfs(index+1);
            //回溯时交换回来
            swap(i,index);
        }
    }
}

int main()
{
    cout << "请输入排列元素个数:" ;
    cin>>length;
    //初始化
    for(int i = 1 ; i<=length ; i++){
        a[i] = i;
    }
    //生成1到length的全排列
    dfs(1);
    return 0;
}

四、运行结果 及分析

此算法运用了交换的思想,但是生成排列并不是按照字典序的排序生成的,细心的读者可以注意到。如果要生成按字典序 生成的全排列请点击这里。此算法也可以解决一些问题,如旅行商问题。稍后我会更新旅行商问题,全排列算法是解决旅行商问题的算法之一。

发布了46 篇原创文章 · 获赞 48 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39559641/article/details/100900105