利用栈实现的全排列
数据结构学到栈了,了解到可以将递归函数的调用看作是函数的压栈,递归函数的结束返回上一层函数可以看作函数的出栈。
之前用递归函数实现过全排列,现在用栈实现一遍。
用栈的第k层保存第k层递归函数,每一层保存平行的变量。。。
问题
假设有一个盒子box[n],里面装着n个小球ball。有个条形、有凹槽的木块per[n],第一个凹槽放一个小球,接着放下一个,放满时,就完成一个排列了。
但第一个凹槽可放的小球有n种肯,第二个凹槽有n-1种可能……最后一个凹槽有一种可能。所有可能就是n的阶乘
#include<iostream>
using namespace std;
#include<vector>
//单个元素的结构体
struct Ball{
char ch;//元素
bool flag;//flag==true 时,该元素未被选择
};
int main(){
vector<int> si;//该层元素从si.back()下标开始扫描box数组
vector<int> sc;//该层元素由sc.back()种机会
int n;
Ball* box; //存放被排列的元素数组
char* per;// 存放已经排列好的元素,存满时输出。
cout << "请输入全排列的元素个数n:" << endl;
cin >> n;
box = new Ball[n];
per = new char[n+1]; per[n] = '\0';//字符串已'\0'结尾
cout << "请输入" << n << "个元素:" << endl;
for(int i = 0; i < n; i++){
cin >> box[i].ch;
box[i].flag = true;
}
cout << endl;
//第一层初始化
si.push_back(0);//该层从0开始扫描box数组
sc.push_back(n-si.size()+1);//该层有n个选择
while(si.size() != 0){//当递归不结束
while(si.back() < n && sc.back() > 0){//该层:box没有被扫描完,且有选择没有被选
if(box[si.back()].flag){//该层种:找到了没有被选择的元素
box[si.back()].flag = false;//该层:标记为不可选择
per[si.size()-1] = box[si.back()].ch;//该层:排列该可选元素
sc[si.size()-1]--;//该层可选择可能性减一
si[si.size()-1]++; //回到该层时,扫描位置为下一个
//进入到下一层
si.push_back(0);
sc.push_back(n-si.size()+1);//下一层的可能性初始化由该层的层数决定。
}
else{
si[si.size()-1]++;//如果被指向的元素不可选择,那么指向下一个
}
}
if(si.size()-1 == n){//如果已经排列好了所有元素则输出,并返回上一层
cout << per << endl;
si.pop_back();
sc.pop_back();
}
//循环:递归未结束,若该层没有下一个可选择元素,恢复已选元素,并返回上一层
while(si.size() && sc.back() == 0){
box[si.back()-1].flag = true;
si.pop_back();
sc.pop_back();
}
//当递归未结束,且该层仍有可选元素时:恢复已选元素。为下一层选择准备。
if(si.size()){
box[si.back()-1].flag = true;
}
}
delete[] per;
delete[] box;
return 0;
}