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

全排列算法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. 你应该再检察一遍, 以确保我没有使用递归调用. ^_^
阅读更多
个人分类: 结构算法
上一篇[ZOJ] 1003 Crashing Balloon
下一篇[模拟] 简单的进程调度模拟
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭