产生[n]所有置换

function ps=permutations(n)
%PERMUTATIONS  产生[n]所有置换
%   ps = permutations( n )     输入正整数n,用换位法产生[n]的所有置换,并按行存入ps返回。

%$Author: WBC$     $Date: 2005/9/30$     $ref: 卢开澄 卢华明  组合数学(第3版)  p28-30$

%初始化
ps=zeros(prod(1:n),n);
A=1:n; %用于存储排列的行向量
D=1:n; % D(k)表示k在{1,2,..,k}这k个数中的位置,即在保持顺序不变的前提下去掉比k大的数后k所在的位置.
       % 为了程序上的统一, 在向左走时, 位置是从1计数, 在向右走时, 位置是从0计数.  这样, 假如当前
       % 置换中某处于活动的最大数将要走的下一个位置是p, 那么在向左走时, 该最大数的位置是p+1, 因为
       % 从1开始计数, 所以p和p+1就是数组A中的实际位置, 从而交换A(p)和A(p+1)就得到了下一个置换,
       % 在向右走时, 该最大数的位置是p-1, 因为从0开始计数, 所以p-1和p在数组A中的实际位置都要加1,
       % 变为p和p+1, 从而也是交换A(p)和A(p+1)就得到了下一个置换. 显然, 无论是向左还是向右, 我们在
       % 交换时的公式是相同的. 当然, 如果不这样做, 可以通过判断实现交换, 效率就低一些.
E=-ones(1,n);%当E(k)=-1时表示数k的箭头方向指向左方, 当E(k)=1时表示数k的箭头方向指向右方

%主循环
ok=1; %一个用来判断循环是否结束的变量
loop=0; %用于标记当前产生的置换要存入ps的行
while ok
    ok=0; %如果下面的程序不能使ok变为1,就结束整个循环,表明已经产生了所有的置换
    loop=loop+1;
    ps(loop,:)=A;
    q=0; %可以看作数k在A中位置相对于在{1,2,..,k}中位置的偏移量
    for k=n:-1:2
        D(k)=D(k)+E(k); %试探下一个位置
        p=D(k);  %数k在下一个置换的{1,2,...,k}中的位置
        if p>0 && p<k   % 试探下一个位置成功, 表示数k走到{1,2,...,k}的中间位置
            p=p+q;
            r=A(p); A(p)=A(p+1); A(p+1)=r;   %交换两个位置p和p+1上的元素
            ok=1;
            break;
        elseif p==k       %表示数k走到{1,2,...,k}的最右端
            E(k)=-1;  %数k改变方向
        else    %此时p==0, 表示数k走到{1,2,...,k}的最左端
            E(k)=1;   %数k改变方向
            q=q+1;  %当数k走到左端时才会使其右边的数的下标有1个偏移
        end
    end
end

你可能感兴趣的:(Date,function,活动,存储)