Рекурсив всегда требует некоторых умственных усилий для поддержания. А для больших чисел факториал легко огромен, и переполнение стека легко станет проблемой.
Для небольших чисел (3 или 4, что встречается чаще всего) несколько циклов довольно просты и просты. К сожалению, ответы с петлями не проголосовали.
Давайте начнем с перечисления (а не перестановки). Просто прочитайте код как псевдо-Perl-код.
$foreach $i1 in @list
$foreach $i2 in @list
$foreach $i3 in @list
print "$i1, $i2, $i3\n"
Перечисление встречается чаще, чем перестановка, но если перестановка необходима, просто добавьте условия:
$foreach $i1 in @list
$foreach $i2 in @list
$if $i2==$i1
next
$foreach $i3 in @list
$if $i3==$i1 or $i3==$i2
next
print "$i1, $i2, $i3\n"
Теперь, если вам действительно нужен общий метод для больших списков, мы можем использовать метод radix. Сначала рассмотрим проблему перечисления:
$n=@list
my @radix
$for $i=0:$n
$radix[$i]=0
$while 1
my @temp
$for $i=0:$n
push @temp, $list[$radix[$i]]
print join(", ", @temp), "\n"
$call radix_increment
subcode: radix_increment
$i=0
$while 1
$radix[$i]++
$if $radix[$i]==$n
$radix[$i]=0
$i++
$else
last
$if $i>=$n
last
Приращение радикала - это, по сути, подсчет чисел (в основе количества элементов списка).
Теперь, если вам нужна перестановка, просто добавьте проверки внутри цикла:
subcode: check_permutation
my @check
my $flag_dup=0
$for $i=0:$n
$check[$radix[$i]]++
$if $check[$radix[$i]]>1
$flag_dup=1
last
$if $flag_dup
next
Редактировать: приведенный выше код должен работать, но для перестановки radix_increment может быть расточительным. Поэтому, если время представляет практическую проблему, мы должны изменить radix_increment на permute_inc:
subcode: permute_init
$for $i=0:$n
$radix[$i]=$i
subcode: permute_inc
$max=-1
$for $i=$n:0
$if $max<$radix[$i]
$max=$radix[$i]
$else
$for $j=$n:0
$if $radix[$j]>$radix[$i]
$call swap, $radix[$i], $radix[$j]
break
$j=$i+1
$k=$n-1
$while $j<$k
$call swap, $radix[$j], $radix[$k]
$j++
$k--
break
$if $i<0
break
Конечно, теперь этот код логически более сложен, я оставлю его для чтения.