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

原创 2007年09月11日 16:43:00
全排列算法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. 你应该再检察一遍, 以确保我没有使用递归调用. ^_^
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

数位全排列算法(可重复)之求和:非递归求法

问题描述:任意给定一个5位以内的整数(其中这个数字各个数位都不含有0,但是允许数位上的数字重复),然后对这个数字的各个数位的数字任意颠倒,成为新的数字组合,然后对这个组合里面的数字进行求和。 举个例...
  • Kaiwii
  • Kaiwii
  • 2012-03-22 16:44
  • 2826

全排列问题算法分析与实现(递归、非递归)

若有数字集合{1,2,3},则其全排列为123、132、213、231、321、312。现给定字符数组,求其字符的全排列。实现了递归与非递归两种方法。

递归分治算法之全排列问题(Java版本)

/** * 递归分治算法学习之全排序 * @author Sking */ package 递归分治; public class FullPermutation { /** * 产生指定...

非递归全排列

非递归全排列无非就是根据一个排列找到下一个; 以1 2 3 4 为例子; 1:先把给定的字符串排序(于小到大); 2:从后到前找到第一个相邻的递增对;例如:1 2 4 3 找到2 4 递增 于...

非递归,按序输出集合的全排列

题目描述 非递归,按序输出集合全排列,是在笔试面试中经常考的问题。递归输出集合的全排列相对来说还是比较简单的,而非递归实现这个问题需要一些小技巧。 全排列是将集合中的元素(可以为数字,...

n个元素的全排列(非递归+去重)

非递归采用的方法是:字典排序找后继;该方法自带去重的效果,并且效率高、顺序自然。 以3个数字的全排列为例,共有 3! = 6 种排列,这6种排列是有大小的,如果按从小到大排列,示意如下: 123 ...

【密码学】生成8位26个字母和数字的全排列(密码字典,密钥)c++代码(非递归高效直接)

生成8位26个字母和数字的全排列(密钥)代码(非递归高效直接) 用C语言或C++,生成一个8位的26个字母和数字的全排列的原代码,例如从:00000000到ZZZZZZZZ。 说明:生成的这个字典会...

非递归数组全排列

首先我想说, 太TM操蛋了, 排序那部分代码一直让人纠结了好久!!!非递归思想, 参考的网上的, 代码自己写的, 勉强算原创吧!!! #include #include int isDesc(c...

非递归全排列实现

非递归全排列实现 #include #include #include #include #include #include #include #include using namespace st...

字典序全排列(非递归方法)

递归实现很简单了,在这就不再赘述,本文主要大体描述一下使用非递归方法进行全排列,该算法被用在了C++的STL库中 [例]字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:   ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)