关闭

[self]全排列算法2 (非递归版本)

714人阅读 评论(0) 收藏 举报
全排列算法2 (非递归版本)
roadtang



在上一次,我写一个简单的全排列算法, 用了递归. 很容易看出来, 用递归很简洁和方便的.
但是递归版的全排列有一个很大的问题.
什么问题呢? 
大家知道,排列在我们眼里实际上一个序列, 一个按特殊顺序排列的序列,我们可能会想第一个,第二个,第三个这个样去访问它. 那么在递归版本里,我们只能用一个很大很大的空间,去将递归的结果全部存储起来,然后再循环着去处理每个元素. 这会浪费很多空间.

再说, 如果我们只想知道第100个排列的样子是什么的呢? 那我们就必须修改上一次写的那个permutation的代码, 让他正好在100那个位置停下来,如果是你自己的代码,这个是可行的, 但是,当你想写一个库的时候, 该怎么办?

我们能不能写一个函数permutation2 ,我们每调用一次它, 就可以得到下一个排列的样子呢?

答案是肯定的.

我们可以使用堆栈来模拟,递归的行为, 从而使以前的递归变得行为可控.
** 注意,  这里并不需要 输入序列是可排序的.. 而且这里是真正的模拟, 不是狗皮膏药**

================= code start ====================
/**-----------------------
   permutation (non-recurision version)

   status permutation.

   road 2008/09/04

   --------------------------*/

#include <stack>
#include <stdio.h>

#define SWAP(x,y) do { x=x^y; y=x^y; x=x^y; } while(0)
using namespace std;


char str[1024];
int len;


enum {
  F_ETNER,
  F_COMEOUT
};

struct pe_ent {
  int i;
  int flag;

  char *s;
  int len;
  pe_ent (int idx, char*str, int slen): i(idx), s(str), len(slen) {}
 
};

typedef stack<pe_ent> PermStack;

void read()
{
  scanf("%s", str);
  len = strlen(str);
}


void per_step(PermStack& stk)
{

  if (stk.empty())
    return;

  while (1)
    {
      pe_ent& e = stk.top();
     
     
      if (e.i<e.len && e.len == 1) // if in  the bottom level.
    {
      //printf("%s", /n); //do.
      e.i = e.i + 1; // mark we have done.
      return;
    }
     
      if (e.i < e.len) // this level isn't done, still need do next permutation.
    {
      if (e.i)
        SWAP(e.s[0], e.s[e.i]);
      stk.push(pe_ent(0, e.s+1, e.len-1));
     
    }
     
      if (e.i >= e.len) //  this level permutation is done, up a level to see if any further actions.
    {
      stk.pop();
     
      if (stk.empty())
        return;
     
      pe_ent& e = stk.top();
      if (e.i)
        SWAP(e.s[0], e.s[e.i]);
      e.i++;
    }
    }
}

void permutation ()
{
  PermStack stk;
 
  char c;
  stk.push(pe_ent(0, str, len));  // push the init seq into the stack. ( call the first func)
  while (!stk.empty())
    {
      per_step(stk);
      printf("%s/n", str);
    }
 
}

int main()
{

  read ();
  permutation();

}

=============== code end ==================

注:
1. struct pe_ent 代表每一个递归,栈上的空间内容.
2. 每调一次per_step, str里就会产生下一个在全排列中序列, permutation反复调用per_step完成任务
3. 你应该再检察一遍, 以确保我没有使用递归调用. ^_^
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:12113次
    • 积分:174
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章存档