比较某排列生成算法的递归版和非递归版的效率

///
//
// 2007-07-11
// By Rappizit@yahoo.com.cn
//
// 比较某排列生成算法的递归版和非递归版的效率
// 该算法生成 List [p..q] 的所有排列方式,看看函数 PermutationRecursion 的代码可以了解该算法
// 也可以参考以下截图【来源:《数据结构算法与应用-C++语言描述》(Sartej Sahni著,汪诗林译)例 1-3】
//
///

《数据结构算法与应用-C++语言描述》(Sartej Sahni著,汪诗林译)例 1-3

:《数据结构算法与应用-C++语言描述》(Sartej Sahni著,汪诗林译)例 1-3

#include <iostream>
#include <time.h>
using namespace std;

template <class T>
inline void Swap (T List [], int a, int b)
{
    if (a != b)
    {
        // 交换 a 和 b
        // 如果要求生成的排列数数列是非递减的,并假设 a 是当前安排位置,
        // 则这里应将 List [a..b] 循环右移
        T temp = List [a];
        List [a] = List [b];
        List [b] = temp;
    }
}

template <class T>
void PermutationRecursion (T List [], int p0, int p, int q)
{
    // 生成 List [p..q] 的所有排列方式
    // p0 是 p 的初始值,输出排列方式时要从 List [p0] 开始
    int i;
    if (p == q)
        {
        // 输出一个排列方式
        //for (i = p0; i <= q; i ++)
        //    {
        //    cout << List [i];    // 比较测试时可以不输出
        //    }
        //cout << endl;
        }
        else    {
            // List [p..q] 有多个排列方式,递归地产生这些排列方式
            for (i = p; i <= q; i ++)
                {
                Swap (List, p, i);
                PermutationRecursion (List, p0, p + 1, q);
                Swap (List, p, i);
                }
            }
}

template <class T>
void PermutationRecursive (T List [], int p, int q)
{
    PermutationRecursion <T> (List, p, p, q);
    // 全部排列方式生成之后 List [p..q] 的元素顺序和最初的一样
}

template <class T>
void Permutation (T List [], int p, int q)
{
    int i, p0 = p, cnt = 0, full = q - p + 1;    // cnt 为已排好的数目, full 为排好所需的数目
    int *Stack = new int [full];
    i = p;    // p 为当前安排位置
    Stack [cnt ++] = i;    // List [i] 为当前安排位置的可安排值
    while (1) {
        if (i == q)    // 最后的位置没有可安排值
            {
            // 输出一个排列方式
            //for (i = p0; i <= q; i ++)
            //    {
            //    cout << List [i]; // 比较测试时可以不输出
            //    }
            //cout << endl;
            // 回退到上一个可安排位置
            do    {
                i = Stack [-- cnt];
                Swap (List, p, i);    // 恢复原顺序
                p --;
                } while    (cnt && i >= q);
            if (!cnt && i >= q )    // 最先的位置没有可安排值
                {
                break;
                }           
            Stack [cnt ++] = ++ i;    // 可安排位置的下一个可安排值为 List [++ i]
            p ++;    // 在 do 循环里面 p 被多减了一次,补回来
            }
        Swap (List, p, i);    // 在 可安排位置 安排 可安排值
        i = ++ p;
        Stack [cnt ++] = i;
        }
    delete Stack;
    // 全部排列方式生成之后 List [p..q] 的元素顺序和最初的一样
}

void main ()
{
    clock_t start, finish;
    double duration1, duration2;
    char List [10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    int n = 10;    // n 为要排列的数的数目

    start = clock ();
    Permutation <char> (List, 0, n-1);    // 非递归
    finish = clock ();
    duration1 = (double)(finish-start)/(double)(CLOCKS_PER_SEC);

    start = clock ();
    PermutationRecursive <char> (List, 0, n-1);    //递归
    finish = clock ();
    duration2 = (double)(finish-start)/(double)(CLOCKS_PER_SEC);

    cout << duration1 << endl << duration2 << endl;
    return;
}

 
///
//
// 测试结果:
// 输出排列方式时递归版比较快,因为递归版的算法复杂度是 O(n!) , 非递归版的大于 O(n!) 而小于 O(nn!) 。
// 不输出排列方式时非递归版有时比递归版快(排列的数少于 10 时),不知为什么呢?
//
// 小结:
// 貌似白费心机来写这个排列生成算法的非递归版本了,T_T,除非某计算机不支持递归,会吗?
// 不过还是锻炼了思维,呵呵。。
// PS:该递归算法不是尾递归的,但是还是可以巧妙地利用堆栈实现非递归版本^_^
//
///

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值