全排列的递归实现 及 用栈改写的非递归实现(Java)

递归实现

全排列的实现思路:

递归思路:n个数全排列相当于先抽取一个数做第一个数,再将剩下n-1个数全排列。所以实现方法是,枚举第一个数的情况,每次将剩下的数送进递归函数,直到剩下一个数。

排列思路:“枚举第一个数的情况”可以采用交换的方式。这步要实现的是把原本的第一个数放进“剩下的数”中。这“剩下的数”从序列第二位开始,顺序无意义,因此实现“删除一个数,再插入一个数”采用交换最方便。

伪代码:

permutation(序列a,序列总长度,“剩下的数”起始序号){

        if(只有一个数)输出结果;return;

        for(int i=起始序号;i<序列总长度,i++){

                交换a[i]和a[起始序号];

                permutation(a,序列总长度,起始序号+1);

                把刚刚交换的换回去。

        }

}

Java代码

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class TestClass {
    static void swap(char[] a,int i,int j){
        char tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
    static void permutationByRecursion(char[] array,int length,int k){
        if(k+1==length){
            System.out.print(array);
            System.out.print(" ");
            return;
        }
        for(int i=k;i<length;i++){
            swap(array,i,k);
            permutationByRecursion(array,length,k+1);
            swap(array,i,k);
        }
    }
    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc=new Scanner(new File("list_testcase.txt"));
        String tmp=sc.next();
        int length=tmp.length();
        char[] array=tmp.toCharArray();
        permutationByRecursion(array,length,0);
    }
}

用栈改写的非递归实现

用栈改写递归,首先要搞清楚栈和递归有什么关系。他们的关联在于,栈后进先出,递归也是后进入的函数先返回。那么这道题“最后进最先出”的是什么?是每一位都经过了交换的序列。

就以abc为例,看一下进出的过程:

水平翻转一下的话类似于后根序遍历的过程 

箭头是递归返回的顺序,反过来就是入栈的顺序

那么按照入栈顺序就可以得到改写思路:初始序列(abc)入栈,初始序列(abc)出栈,多个子序列(a bc,b ac,c ba)入栈,一个子序列(cba)出栈,该子序列的所有子序列(c ba,c ab)入栈,如此循环往复。如果某代子序列已经排完则在出栈的同时打印结果。

如何记录已经交换到了第几位?(即递归写法中的k)没有想到什么巧妙的方法,就用了自己写的类似于c++的map类

伪代码:

Stack.push(map(Array,0));

while(top!=null){//循环直到栈空

        tmp=Stack.pop();//弹出栈顶

        k=tmp.second;

        if(k+1==tmp.length)打印并continue;//已经排完了

        for(k<=i<tmp.length){

                交换tmp.first[ k ]和tmp.first[ i ];

                Stack.push(tmp的拷贝,但second+1);//注意不能是tmp,因为传进去的是地址

                再换回来;

        }

}

Java代码:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
class MyMap{
    char[] first;
    int second;
    public MyMap(char[]first,int second){
        this.first=first.clone();
        this.second=second;
    }
}
public class TestClass {
    static void swap(char[] a,int i,int j){
        char tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
    static void permutationByNoRecursion(char[] array){
        MyStack stack=new MyStack();
        stack.push(new MyMap(array,0));
        while(stack.getTop()!=null){
            MyMap tmp= (MyMap) stack.pop();
            int k=tmp.second;
            if(k+1==array.length){
                System.out.print(tmp.first);
                System.out.print(" ");
                continue;
            }
            for(int i=k;i<array.length;i++){
                swap(tmp.first,i,k);
                stack.push(new MyMap(tmp.first, tmp.second+1));
                swap(tmp.first,i,k);
            }
        }
    }
    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc=new Scanner(new File("list_testcase.txt"));
        String tmp=sc.next();
        int length=tmp.length();
        char[] array=tmp.toCharArray();
        permutationByNoRecursion(array);
    }
}

补充:输出长度为 m 的字符串中取 n 个字符构成的所有全排列

static void permutationByRecursion(char[] array,int length,int k){
        if(k+1==length){
            System.out.print(array);
            System.out.print(" ");
            return;
        }
//        outer:
        for(int i=k;i<length;i++){
//            for (int j=k;j<i;j++){
//                if(array[j]==array[i])continue outer;
//            }
            swap(array,i,k);
            permutationByRecursion(array,length,k+1);
            swap(array,i,k);
        }
    }
    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc=new Scanner(new File("list_testcase.txt"));
        String tmp=sc.next();
        int length=tmp.length();
        char[] array=tmp.toCharArray();
        char[]res =new char[3];
        Combination(array,res,length,3,0,0,3);
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值