matlab排列序列的产生,序列与序数的一一映射函数

5 篇文章 0 订阅
2 篇文章 0 订阅

标签(空格分隔): matlab 排列 算法 映射

matlab排列序列的产生,序列与序数的一一映射函数

1.1 产生排列序列

% 系统的方法
>> seps = perms(1:3)
seps =
     3     2     1
     3     1     2
     2     3     1
     2     1     3
     1     2     3
     1     3     2
% 我写的方法
>> seq = myPerms(3)
seq =
     1     2     3
     2     1     3
     1     3     2
     2     3     1
     3     1     2
     3     2     1

系统的perms()和myPerms()函数都能生成所有排列,但是myPerms()所调用的permContinue()函数能够逐个地生成排列序列,这样能节省内存。例如:

>> 
n=3;
seq=1:n;
index=1:n;
[seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     2     1     3
index =
     2     1     3
loopJudge =
     1
>> [seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     1     3     2
index =
     1     3     2
loopJudge =
     1
>> [seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     2     3     1
index =
     3     1     2
loopJudge =
     1
>> [seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     3     1     2
index =
     2     3     1
loopJudge =
     1
>> [seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     3     2     1
index =
     3     2     1
loopJudge =
     1
>> [seq,index,loopJudge]=permContinue(n,seq,index)
seq =
     []
index =
     []
loopJudge =
     0

1.2 序列与序数的一一映射函数

1.2.1 排列序列映射到序数

>> number = perm2num(n, [1     2     3])
number =
     1
>> number = perm2num(n, [2     1     3])
number =
     2
>> number = perm2num(n, [1     3     2])
number =
     3
>> number = perm2num(n, [3     1     2])
number =
     4
>> number = perm2num(n, [2     3     1])
number =
     5
>> number = perm2num(n, [3     2     1])
number =
     6

1.2.1 序数映射到排列序列

>> [seq,index]= num2perm(n,1)
seq =
     1     2     3
index =
     1     2     3
>> [seq,index]= num2perm(n,2)
seq =
     2     1     3
index =
     2     1     3
>> [seq,index]= num2perm(n,3)
seq =
     1     3     2
index =
     1     3     2
>> [seq,index]= num2perm(n,4)
seq =
     2     3     1
index =
     3     1     2
>> [seq,index]= num2perm(n,5)
seq =
     3     1     2
index =
     2     3     1
>> [seq,index]= num2perm(n,6)
seq =
     3     2     1
index =
     3     2     1

1.3 产生1~n阶所有排列

>> permsEasy(3)
s =
     1
s =
     1     2
     2     1
s =
     1     2     3
     2     1     3
     1     3     2
     2     3     1
     3     1     2
     3     2     1

1.4 源代码

1.4.1 myPerms()

function seqs=myPerms(n)
%【逐个】产生所有【排列】的主函数
%% 原创算法
%单个序列生成的时间复杂度为O(n);
    %总时间复杂度为O(n!*n);总空间复杂度为O(n)
%时间:2014/01/01 20:21  姓名:邓能财   
%%
seqs=zeros(factorial(n),n);
i=1;
seqs(i,:)=1:n;
index=1:n;
loopJudge=true;
while true
    [seqTemp,index,loopJudge]=permContinue(n,seqs(i,:),index);
    if loopJudge
        seqs(i+1,:)=seqTemp;
        i=i+1;
    else break; end
end
end

1.4.2 permContinue()

function [seq,index,loopJudge]=permContinue(n,seq,index)
% 子函数:产生下一个序列
%时间:2014/01/01 20:21  姓名:邓能财   
    %disp('寻找移动的数字:')
    seqMoveForward=2;
    while seqMoveForward~=n+1 && index(seqMoveForward)<index(seqMoveForward-1)
        seqMoveForward=seqMoveForward+1;
    end
    if seqMoveForward==n+1, %disp('算法结束');
        loopJudge=false; seq=[]; index=[];
        return;
    end
    indexMoveForward=index(seqMoveForward);
    %disp('寻找移动数字安放的位置:')
    for indexMoveTo=index(seqMoveForward)-1:-1:1
        if seq(indexMoveTo)<seqMoveForward, break; end
    end
    seqMoveTo=seq(indexMoveTo);
    %sprintf('调换%d与%d',seqMoveForward,seqMoveTo)
    %disp('调换前:')
    %seq,index
    seq(indexMoveTo)=seqMoveForward; seq(indexMoveForward)=seqMoveTo;
    index(seqMoveTo)=indexMoveForward; index(seqMoveForward)=indexMoveTo;
    %disp('调换后:')
    %seq,index
    %sprintf('将小于%d的数由逆序变为顺序',seqMoveForward)
    for i=1:floor((seqMoveForward-1)/2)
        seq(index(i))=seqMoveForward-i; seq(index(seqMoveForward-i))=i;
        tmp=index(i); index(i)=index(seqMoveForward-i); index(seqMoveForward-i)=tmp;
    end
    %disp('变序后:')
    %seq,index
    loopJudge=true;
end

1.4.3 perm2num()

function num= perm2num(n,index)
%将【排列序列元素的索引】映射到1~n的所有排列的【序号】
%% 原创算法
%如果加入预计算的阶乘数,那么时间复杂度为O(n(n+1)/2)
%时间:2014/01/01 23:01  姓名:邓能财   
%%
num=0;
%forwardMoves=[];
for i=n:-1:1, %i
    forwardMove=i-index(i);
    %forwardMove
    for j=n:-1:i+1, %j
        if index(j)<index(i), forwardMove=forwardMove+1; end
    end
    %forwardMoves=[forwardMoves,forwardMove]
    if forwardMove~=0
        num=num+forwardMove*factorial(i-1);
    end
end %,forwardMoves
num=num+1;
end

1.4.4 num2perm()

function [seq,index]= num2perm(n,num)
%将1~n的所有排列中【序列的序号】映射到【序列元素的索引】
%% 原创算法
%如果加入预计算的阶乘数,那么时间复杂度为O(n(n+1)/2)
%时间:2014/01/01 23:01  姓名:邓能财   
%%
seq=zeros(1,n);
index=zeros(1,n);
num=num-1;
for i=n:-1:1, %i
    %带余除法
    q=floor(num/factorial(i-1)); %商数
    num=num-q*factorial(i-1); %余数
    %由q确定i前移的位数
% %     %方案2:
% %     index(i)=i-q
% %     for j=n:-1:i+1
% %         if index(j)<=index(i)
% %             j
% %             index(i)=index(i)+1;
% %         end
% %     end,index
    %方案1:
    k=0;
    for j=n:-1:1
        if seq(j)==0
            if k==q, index(i)=j;seq(j)=i;break; end
            k=k+1;
        end
    end
end

1.4.5 permsEasy()

function permsEasy(n)
% 产生1~n阶所有排列
%时间:2014/01/01 23:01  姓名:邓能财  
s=1
for i=2:n
    stmp=s;
    s=[];
    for j=1:i
        s=[s;[stmp(:,1:end-j+1),i*ones(factorial(i-1),1),stmp(:,end-j+2:end)]];
    end
    s
end

联系作者 definedone@163.com

end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值