----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
这个其实也是我做的一道基础测试题,这道题给我感觉还是蛮难的,我也是看了网上关于全排列的递归算法之后才写出来的,我觉得把这个小程序搞懂了,递归基本也就弄明白了,写这个程序的时候还是费了点劲的。如果哪位仁兄有更好的方法还望@我
import java.util.Enumeration;
import java.util.Stack;
/**
* 第6题:编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符
* 例如:原始字符串是"abc",打印得到下列所有组合情况
* "a" "b" "c"
* "ab" "bc" "ca" "ba" "cb" "ac"
* "abc" "acb" "bac" "bca" "cab" "cba"
*
* 程序说明:
* 1、程序大致可以分为两个部分,组合、排列
* 2、先求出字符串的全部组合
* 3、而后,分别对这些组合进行全排列
* 4、该程序无法应对重复字符的情况
*
* @author shine
*
*/
public class Test6 {
//创建静态变量以便函数间交换数据
static String[][] stringss;
static String[] strings;
static int index;
//主函数,世界从这里展现
public static void main(String[] args){
String stringsmain = "abcd";
char[] chars = stringsmain.toCharArray();
stringss = new String[chars.length][];
combiantion(chars);//调用combination方法,找到组合,并存储在string[][]中
//遍历stringss[][]数组
for(int indexout=0; indexout<stringss.length; indexout++){
for(int indexin=0; indexin<stringss[indexout].length; indexin++){
char[] arr = stringss[indexout][indexin].toCharArray();
permutation(arr, 0, arr.length);//将组合传入permutation方法,并进行全排列
}
System.out.println();
}
}
//该方法用于求解字符串的全部组合
public static void combiantion(char[] chs){
if(chs.length == 0)
return;
Stack<Character> stack = new Stack<Character>();
for(int i = 1; i <= chs.length; i++){
int num = factorial(chs.length)/(factorial(i)*factorial(chs.length-i));
//求出不同字符串,不同长度下的组合的数量num
strings= new String[num];
index = 0;
//调用combine方法,求该字符串长度为i时的组合情况,并将数据保存到strings数组中
combine(chs, 0, i, stack);
stringss[i-1] = strings;
}
}
//定义num的阶乘
public static int factorial(int num){
int result = 1;
for(;num>=1;num--){
result *=num;
}
return result;
}
//该方法用于求解字符串在长度为number时的组合情况,主要利用了递归思想
public static void combine(char[] chars, int begin, int line, Stack<Character> stack){
//定义跳出递归的条件
if(line == 0){
Enumeration<Character> enumer = stack.elements();
strings[index] = "";
while(enumer.hasMoreElements()){
strings[index] += enumer.nextElement().toString();
}
index++;
return;
}
if(begin == chars.length){
return;
}
stack.push(chars[begin]);//利用堆栈缓存数据
combine(chars, begin+1, line-1, stack);
stack.pop();
combine(chars, begin+1, line, stack);
}
/**
* combine方法实现过程分析:
* 为简化问题,假设需要排序的字符串是“abc”
* 单个字符,对应后面排列后显示的第一行:
* begin=0, line=1 , chars.length=3
****** 首先,将a存入stack中,而后调用combine(chars,begin+1,line-1,stack)开始递归
* begin=1, line=0 , ....= 3 ==> line==0,读取stack中的a-------, index++,return
* stack.pop() 情空缓存的a
* 调用combine(chars,begin+1,line,stack)
* begin=1, line=1....
* chars[begin]=chars[2]=b 被存入stack
* begin=2, line=0.....输入b-------
* 清空缓存b
* begin=2, line=1....
* 缓存c
* begin=3, line=0....
* 输出c----------
* 清空c
* begin=3, line=1....begin==chars.length..==> return
* return回到第二层是}。。。。继续回到第一层,依然是}==>程序结束,
* 完成第一行输出:a, b, c 继续combiantion中的for循环==>开始第二行
****** 两个字符,对应第二行:
* begin=0, line=2
* 存储a。。。
* begin=1, line=1
* 存储b。。。
* begin=2, line=0 ==>输出 ab return------
* 清空b
* begin=2, line=1
* 存储c。。
* begin=3, line=0 ==>输出 ac return-----
* 清空c。。
* begin=3, line=1 ===> return
* }
* },再次后退,回到第一层
* 清空a。。。
* begin=1,line=2
* 缓存b。。。此时b放在了第一位
* begin=2,line=1
* 读取c。。。
* begin=3,line=0 ==>输出bc return------
* 清空c。。。
* begin=3,lin=1 ==>return
* }
* 清空b。。。
* begin=2,line=2
* 读取c。。。此时c放在了第一位
* begin=3,line=1 ==>return
* 清空c。。。
* begin=3,line=1 ==》retuen
* }
* }
* }程序结束,进入下一个for循环,开始三个字符的组合
*******
*三个元素的情况
* begin=0, line=3
* 缓存a
* begin=1,line=2
* 缓存b
* begin=2,line=1
* 缓存c
* begin=3,line=0 输出abc return
* 清空c
* begin=3,line=1 return
* }
* 清空b
* begin=2,line=2
* 读取c
* begin=3,line=1 ==>return
* 清空才
* begin=3,line=2 ==>return
* }
* }
* 清空a
* begin=1,line=3 ==>return
* }
* 程序就此结束,完成全部组合的获取
*
* 全排列情况同理
*
*/
//用于对字符数组进行全排列
public static void permutation(char[] arr, int index, int size){
//递归的出口,并用于输出当前排列
if (index+1 == size){
System.out.print("\"");
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "");
}
System.out.print("\"\t");
}
else {
for (int i = index; i < size; i++) {
//如果arr[i]和arr[index]相同则不进行操作,避免了存在相同元素时的重复排序,但由于组合的方法没有对相同字符加以辨别,所以最终效果并不好
if(i != index && arr[i] == arr[index])
continue;
swap(arr, i, index);//如果不相同则交换两元素
permutation(arr, index+1, size);//进入下一层,下一层会对后面的元素进行排序或者打印出当前的排列
swap(arr, i, index);//再次换回交换前的状态,以便为下一个排列做准备
}
}
}
//用于交换数组元素的方法
public static void swap(char[] arr, int idx1, int idx2) {
char temp = arr[idx1];
arr[idx1] = arr[idx2];
arr[idx2] = temp;
}
}