排列的非递归算法

#排列的非递归算法(C++)
本人大一新生啊,学习线性代数时,想写一个程序能计算n阶行列式的值。
框架搭好了,结果发现处理不好列标(处理列标就是一个对列标进行全排列过程),我上网查到的主要是递归方法,但是我感觉这不好用啊,因为递归方法会一次性输出所有结果(我现在C++水平还太菜,不太会改)。再加上我确实想锻炼一下自己,于是我想了很长时间,终于想到了一种非递归算法。。。上代码:
##前期准备

//     0 1 2 3   //将输出序号的数组想象成一个表格,#代表选中
//a[0] #         //a[n]中n越小就称a[n]位越高,a[n]的值越大表示越往后
//a[1]   #       //从低位开始往后移,移到低位和更低位的不能移为止,再移高一位的
//a[2]     #     //高一位的也如此
//a[3]       #   //这种排序方法顺便给序号做了个大小排序
#include <iostream>       
using namespace std;      
//这是用来整理所处理的项后面所有的项的函数
void set(int a[],int i,int size)  //当前项固定后,需要将其余项按顺序摆放,如365要摆成356
{
 for(int x=i;x<size;x++)
 {
  a[x]=0;  //每次摆放都要从0位开始
  for(int y=0;y<x;y++)
  {
   for(int z=0;z<x;z++)
   {
    if(a[z]==a[x])  //与高位项有冲突
     a[x]++;  //向后移一位
   }
  }
 }
}
//这是用来设置a[i]位置的函数
void setai(int a[],int i,int size)  //只要现在正在处理的项与任何高级位的项有冲突,则将其一直向后移
{
 for(int m=0;m<size;m++)  //至多移动size-1次,查这么多次就够了
 {
  for(int n=0;n<i;n++)  //每次移动都检查高位的项与现有项有没有冲突
  {
   if(a[n]==a[i])  //有冲突
    a[i]++;  //向后移一位
  }
 }
}
void print(int a[],int size)  //数组打印函数,没啥好说的
{
 for(int i=0;i<size;i++)
  printf("%d  ",a[i]);
 printf("\n");
}
int main()
{
 int n;
 cout<<"请输入排列几个数:"<<endl;
 cin>>n;
 int* ptr=new int[n];  //接收用户输入的数的数组
 int* a=new int[n];  //用来存放序号的数组
 int* temp=new int[n];  //存放最终结果的数组
 for(int n1=0;n1<n;n1++)
  a[n1]=n1;
 cout<<"请输入所要排列的数:";
 for(int n2=0;n2<n;n2++)
  cin>>ptr[n2];
 for(int n3=0;n3<n;n3++)  //按原顺序摆放的情况会在下方的循环中被略过,所以特别处理一下
  temp[n3]=ptr[a[n3]];
 print(temp,n);
 //以上为事先准备

#//这是主要算法

 int i,cai,reset;  //cai:a[i]的副本 reset:重置a[i]
 i=n-1;  //从后向前检索
while(i>=0)  //循环生成不重复序号
 {
  reset=a[i];  //记录a[i]的初始值
  while(i!=n-1)  //检查后面的项是否全部不能再向后移动
  {
   cai=a[i+1];  //副本暂时存储当前a[i+1]的值
   a[i+1]++;  //为了检查能不能向后移,得先自增1
   setai(a,i+1,n);
   if(a[i+1]>n-1)  //越界
   {
    a[i+1]=cai;  //检查而已,不能修改任一项的值
    break;  //若越界,则说明下一项已经不能再向后移动了,应结束循环
   }
   else
   {
    a[i+1]=cai;  //检查而已,不能修改任一项的值
    i++;  //不越界,说明下一项还可以向后移,则i++以继续检查下一项
   }
  }
  a[i]++;  //为了检查能不能向后移,得先自增1试试看
  setai(a,i,n);  //检查所有冲突
  if(a[i]>n-1)  //越界。越界代表一个结果的确实解决
  {
   a[i]=reset;  //重置a[i]为初始值
   i--;  //i--,再检查上一项是否越界
   continue;  //结果已经找到,不必再次打印,否则会重复
  else
  {
   set(a,i+1,n);  //若不越界,则对低位项进行整理
   i++;  //i++,处理对象变为下一项,再次进行前面的判断
  }
  for(int n3=0;n3<n;n3++)
  {
   temp[n3]=ptr[a[n3]];  //按已经确定的顺序排列
  }
  print(temp,n);  //输出
 }
//最后释放动态分配的内存
 delete[] ptr;
 delete[] a;
 delete[] temp;
 system("pause");
 return 0;
}

总之,这个算法的基本思想是处理某一项时,先看这一项的下一项能不能向后移,如果可以,再判断下一项,并一直进行以上操作,直到找到一个不能再向后移动的项,将它的上一项向后移。如果后移后不越界,按顺序排好后面的项,输出。
。。。。
写完这个,我真的不得不感叹,这个算法真是被逼出来的啊。要是我递归用的好,肯定不会写这玩意了。
。。。。
我虽然学的是计算机,但毕竟才大一,水平不高是肯定的,欢迎各位前辈指导!
###转载表明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值