全排列算法的非递归实现与递归实现的方法(C++)

全排列算法是计算机科学领域中的一个经典问题,其功能是对给定的一组数进行全排列。在本文中,我们将对该算法的非递归实现和递归实现方法进行详细讲解。本文的代码示例基于C++语言。

非递归实现方法

算法思路

假设我们想对n个数进行全排列,那么我们可以首先将这n个数按照升序排列,然后使用以下步骤:

  1. 把这n个数的全排列问题转化为n-1个数的全排列问题;

  2. 依次取出每一个数作为当前处理的第一个数,然后将剩下的n-1个数进行全排列;

  3. 将当前处理的第一个数与所有的n-1个数交换位置,然后将剩下的n-1个数进行全排列。

可以通过循环实现上述算法,具体实现可以参考以下代码:

实现代码

#include <iostream>
#include <vector>
using namespace std;

void Swap(vector<int>& nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

void Print(vector<int>& nums) {
    for (int i = 0; i < nums.size(); ++i) {
        printf("%d ", nums[i]);
    }
    putchar('\n');
}

void NonRecursivePermute(vector<int>& nums) {
    Print(nums);
    int n = nums.size();
    vector<int> p(n, 0);
    for (int i = 1; i < n; ++i) {
        p[i] = i;
    }
    int i = 1;
    while (i < n) {
        if (p[i] < i) {
            if (i % 2 == 1) {
                Swap(nums, 0, i);
            } else {
                Swap(nums, p[i], i);
            }
            Print(nums);
            ++p[i];
            i = 1;
        } else {
            p[i] = 0;
            ++i;
        }
    }
}

int main() {
    vector<int> nums{1,2,3};
    NonRecursivePermute(nums);
    return 0;
}

上述代码是一种非递归实现的全排列算法。对于输入的数组,我们首先输出初始的排列,然后使用一个数组p来记录每个元素应该在哪个位置,如p[i]表示当前第i个元素应该放置在哪个位置。在每次迭代中,我们检查当前的p[i]是否小于i,如果是,则说明i位置还有可交换的元素,我们需要交换它们的位置,并且对交换后的数组再次执行全排列操作;如果p[i]等于i,则说明当前位置已经没有可交换的元素,我们需要将p[i]置为0,继续对下一个位置执行全排列操作。

示例说明

我们以{1,2,3}为例,来说明上述算法的执行过程:

  1. 初始排列为{1,2,3},输出该排列;

  2. 交换位置0和位置1的元素,得到排列{2,1,3},输出该排列;

  3. 交换位置1和位置2的元素,得到排列{2,3,1},输出该排列;

  4. 交换位置0和位置1的元素,得到排列{3,2,1},输出该排列;

  5. 交换位置1和位置2的元素,得到排列{3,1,2},输出该排列;

  6. 交换位置0和位置1的元素,得到排列{1,3,2},输出该排列;

  7. 交换位置1和位置2的元素,得到排列{1,2,3},输出该排列。

递归实现方法

算法思路

利用递归求解全排列问题,我们可以将该问题分解为交换两个位置的元素和后面一段数组进行全排列两步。具体地,我们从数组的第一个位置开始遍历,每次将当前位置的元素与后面的每一个元素进行交换,并将交换后的后面一段数组进行全排列,然后再进行回溯,将元素的位置改回来。

具体实现可以参考以下代码:

实现代码

#include <iostream>
#include <vector>
using namespace std;

void Swap(vector<int>& nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

void Print(vector<int>& nums) {
    for (int i = 0; i < nums.size(); ++i) {
        printf("%d ", nums[i]);
    }
    putchar('\n');
}

void RecursivePermute(vector<int>& nums, int begin, int end) {
    if (begin == end) {
        Print(nums);
        return;
    }
    for (int i = begin; i <= end; ++i) {
        Swap(nums, begin, i);
        RecursivePermute(nums, begin+1, end);
        Swap(nums, begin, i);
    }
}

int main() {
    vector<int> nums{1,2,3};
    RecursivePermute(nums, 0, nums.size()-1);
    return 0;
}

上述代码是一种递归实现的全排列算法。对于输入的数组,我们从第一个位置开始遍历,将当前位置的元素与后面的每一个元素进行交换,然后对交换后的数组后面一段进行全排列操作,直到到达数组末尾;在最终到达数组末尾之后,我们输出得到的一个排列,然后通过回溯将数组中的元素位置改回来,依次遍历完整个数组。至此,我们完成了基于递归的全排列算法的实现。

示例说明

以{1,2,3}为例,我们来说明基于递归的全排列算法的执行过程:

  1. 对于当前要处理的数组{1,2,3},选取第1个元素1作为第一个位置,与后面的两个元素2,3交换,然后求解{2,3}的全排列,得到{2,3},然后进行回溯,将交换过的元素位置改回来,即得到{1,2,3};

  2. 对于当前要处理的数组{1,2,3},选取第2个元素2作为第一个位置,与后面的两个元素1,3交换,然后求解{1,3}的全排列,得到{1,3},然后进行回溯,将交换过的元素位置改回来,即得到{1,2,3};

  3. 对于当前要处理的数组{1,2,3},选取第3个元素3作为第一个位置,与后面的两个元素1,2交换,然后求解{1,2}的全排列,得到{1,2},然后进行回溯,将交换过的元素位置改回来,即得到{1,2,3};

  4. 对于当前要处理的数组{1,2,3},得到所有的全排列{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,2,1},{3,1,2}。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:全排列算法的非递归实现与递归实现的方法(C++) - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • C语言冒泡排序法的实现(升序排序法)

    冒泡排序是一种简单的排序算法。它会依次比较相邻两个元素,如果它们的顺序错误就交换它们的位置,直到所有元素都排列成功。 以下是C语言冒泡排序的实现过程: 1.先定义数组 代码示例: int a[10] = {23, 56, 12, 45, 9, 17, 98, 67, 41, 3}; 2.开始排序 首先,我们需要使用两层循环来遍历每一个元素。 外层循环从第一个…

    算法与数据结构 2023年5月19日
    00
  • C语言深入探究直接插入排序与希尔排序使用案例讲解

    C语言深入探究直接插入排序与希尔排序使用案例讲解 直接插入排序 算法描述 直接插入排序的基本思想是将一个记录插入到已经排序好的有序表中,从而得到一个新的、记录数增加1的有序表。具体算法流程如下: 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素大于新元素,将该元素移到下一位置 重复步骤3,直到找到已排…

    算法与数据结构 2023年5月19日
    00
  • 常用的 JS 排序算法 整理版

    下面是对“常用的JS排序算法 整理版”的完整攻略的详细讲解。 一、排序算法介绍 排序是计算机科学中的一个基本问题,它的目的是对一组元素进行升序或降序排列。JS中常用的排序算法包括 冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序等。 二、常用排序算法示例 下面是两个常用排序算法的示例: 1. 冒泡排序 冒泡排序是一种简单的排序算法,它重复遍历要排序…

    算法与数据结构 2023年5月19日
    00
  • Java 十大排序算法之计数排序刨析

    Java 十大排序算法之计数排序刨析 算法介绍 计数排序是一个时间复杂度为O(n+k)的非基于比较的排序算法,其中n是待排序元素的个数,k是待排序元素的范围,即待排序元素的最大值减去最小值再加1。 算法通过构建一个长度为k的计数数组来统计每个元素出现的次数,然后借助计数数组按顺序输出每个元素,就完成了排序过程。 因为计数排序是非基于比较的算法,因此可以在一定…

    算法与数据结构 2023年5月19日
    00
  • JavaScript中几种排序算法的简单实现

    JavaScript中几种排序算法的简单实现 排序算法在计算机科学中是一个基本问题。不同的排序算法具有不同的时间和空间复杂度,选择合适的排序算法可以提高程序的效率。本文介绍了JavaScript中几种排序算法的简单实现,包括冒泡排序、选择排序、插入排序、归并排序和快速排序。 冒泡排序 冒泡排序是最简单的排序算法之一。它重复遍历列表,比较相邻的元素,并交换它们…

    算法与数据结构 2023年5月19日
    00
  • PHP哈希表实现算法原理解析

    PHP哈希表实现算法原理解析 什么是哈希表 哈希表又称为散列表(Hash Table),是根据关键码值(Key-Value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到 Hash 表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数(Hash Function),存放记录的数组叫做哈希表(Hash Table)。 PHP哈希表实现…

    算法与数据结构 2023年5月19日
    00
  • JavaScript实现快速排序(自已编写)

    下面是详细的讲解JavaScript实现快速排序的完整攻略。 1. 什么是快速排序? 快速排序是一种常用的排序算法,通过分割(partition)和递归分治的思想来快速排序一个数组,在平均情况下它的时间复杂度为 $O(n\log n)$,也是一种不稳定的排序方法。 2. 快速排序的实现过程 2.1 分割 对一个数组进行快速排序的过程就是先将其从中间分割成两部…

    算法与数据结构 2023年5月19日
    00
  • C++详细讲解图的拓扑排序

    C++详细讲解图的拓扑排序 什么是拓扑排序 拓扑排序是对于有向无环图(Directed Acyclic Graph)的一种排序,其输出结果为图中每个节点的线性先后序列,满足如果存在一条从节点 A 到节点 B 的路径,则在序列中节点 A 出现在节点 B 的前面。 什么是有向无环图(DAG) 有向无环图是不包含环路并且有一个或多个源点和汇点的有向图。其中源点指没…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部