Реализации алгоритмов/Алгоритм Нарайаны: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
Исправление форматирования, поправки к коду
Строка 4: Строка 4:
Во всех приведенных ниже реализациях <code>a</code> — массив, в котором в прямом порядке записана перестановка, а <code>n</code> — количество элементов в перестановке.
Во всех приведенных ниже реализациях <code>a</code> — массив, в котором в прямом порядке записана перестановка, а <code>n</code> — количество элементов в перестановке.


==[[w:C (язык программирования)|C]]==
== C ==
<source lang="cpp">
<source lang="cpp">
typedef int T;
int NarayanaNextPerm (int *a, int n)
{
int i, j, l;


void swapItems (T *array, unsigned index_1, unsigned index_2) {
//Шаг 1
T temp = array[index_1];
for (j = n - 2; j >= 0 && a[j] >= a[j + 1]; j--);
array[index_1] = array[index_2];
array[index_2] = temp;
}


int NarayanaNextPermutation (T *a, int n) {
//Шаг 2
int i, j, l;
/* Шаг № 1 */
for (j = n - 2; j >= 0 && a[j] >= a[j + 1]; --j);
/* Шаг № 2 */
if (j == -1)
if (j == -1)
return 0;
return 0;
for (l = n - 1; a[j] >= a[l]; --l);

for (l = n - 1; a[j] >= a[l]; l--);
swapItems(a, l, j);
++j;

/* Шаг № 3 */
swap(&a[l], &a[j]);
for (i = 0; i < (n - j + 1) >> 1; ++i)

swapItems(a, j + i, n - i - 1);
j++;

//Шаг 3
for (i = 0; i < (n - j + 1) / 2; i++)
swap(&a[j + i], &a[n - i - 1]);

return j;
return j;
}
}
</source>
</source>


=== Паскаль ===
==[[w:Паскаль (язык программирования)|Pascal]]==
<source lang="pascal">
<source lang="pascal">
type T = integer;
function NarayanaNextPerm(var a: array of integer; n: integer): integer;

var
i, k, t, tmp: integer;
function NarayanaNextPermutation (var a: array of T; n: integer): integer;
var i, k, l: integer;
procedure SwapItems (index_1, index_2: word);
var temp: T;
begin
temp := a[index_1];
a[index_1] := a[index_2];
a[index_2] := temp
end;
begin
begin
//Шаг 1
{ Шаг 1 }
k := n - 2;
k := n - 2;
while (k >= 0) and (a[k] >= a[k+1]) do
while (k >= 0) and (a[k] >= a[k + 1]) do
k := k - 1;
k := k - 1;
if k = -1 then

NarayanaNextPermutation := 0
if k = -1 then begin
else
NarayanaNextPerm := 0;
Exit;
begin
{ Шаг № 2 }
end;
l := n - 1;

while (l >= k + 1) and (a[k] >= a[l]) do
//Шаг 2
t := n - 1;
l := l - 1;
while (t >= k + 1) and (a[k] >= a[t]) do
SwapItems(k, l);
t := t - 1;
{ Шаг № 3 }
for i := k + 1 to (n + k) div 2 do
tmp := a[k];
a[k] := a[t];
begin
a[t] := tmp;
l := n + k - i;
SwapItems(i, l)

end;
//Шаг 3
NarayanaNextPermutation := i
for i := k + 1 to (n + k) div 2 do begin
t := n + k - i;
end
tmp := a[i];
a[i] := a[t];
a[t] := tmp;
end;
NarayanaNextPerm := i;
end;
end;
</source>
</source>


=== PHP ===
==[[w:PHP|PHP]]==
===Вариант № 1===
<source lang="PHP">
<source lang="PHP">
function narayana($in, $n)
function NarayanaNextPermutation ($a, $n) {
$out = $a;
{
$out = $in;
// Шаг № 1
$k = $n - 2;
$k = $n - 2;
while ($k >= 0 && $out[$k] >= $out[$k + 1])
while ($k >= 0 && $out[$k] >= $out[$k + 1]) {
{
--$k;
$k--;
}
}
if (-1 == $k) {

if (-1 == $k)
return false;
{
return false;
}
}
// Шаг № 2

$t = $n - 1;
$t = $n - 1;
while ($t >= 0 && $t >= $k + 1 && $out[$k] >= $out[$t])
while ($t >= 0 && $t >= $k + 1 && $out[$k] >= $out[$t]) {
{
--$t;
$t--;
}
}
$tmp = $out[$k];

$tmp = $out[$k];
$out[$k] = $out[$t];
$out[$k] = $out[$t];
$out[$t] = $tmp;
$out[$t] = $tmp;
// Шаг № 3

for ($i = $k + 1; $i < ceil(($n + $k) / 2); ++$i) {
//Шаг 3
for ($i = $k + 1; $i < ceil(($n + $k) / 2); $i++)
$t = $n + $k - $i;
$tmp = $out[$i];
{
$t = $n + $k - $i;
$out[$i] = $out[$t];
$tmp = $out[$i];
$out[$t] = $tmp;
$out[$i] = $out[$t];
$out[$t] = $tmp;
}
}


Строка 105: Строка 102:
</source>
</source>


===Вариант № 2===
{{BookCat}}


=== PHP ===
Вариант с выводом справа налево:
Вариант с выводом справа налево:
<source lang="PHP">
<source lang="PHP">
$b="123456789";
$b = "123456789";
$a=strrev($b);
$a = strrev($b);
while ($a !=$b) {
while ($a !=$b) {
$i=0;
$i = 0;


while($a[$i] > $a[$i-1]) {
while($a[$i] > $a[$i - 1]) {
$i++;
$i++;
}
}
$j=0;
$j = 0;
while($a[$j] < $a[$i]) {
while($a[$j] < $a[$i]) {
++$j;
}


$c = $a[$j];
$j++;
$a[$j] = $a[$i];
}
$a[$i] = $c;


$x = strrev(substr($a, 0, $i));
$c=$a[$j];
$a[$j]=$a[$i];
$y = substr($a, $i);
$a[$i]=$c;

$x=strrev(substr($a, 0, $i));
$y=substr($a, $i);

print $a=$x.$y;
print ‘<br/>’;


print $a = $x . $y;
print ‘<br/>’;
}
}
</source>
</source>

{{BookCat}}

Версия от 15:48, 23 апреля 2017

Алгори́тм Нарайа́ны — нерекурсивный алгоритм, генерирующий по данной перестановке следующую за ней в лексикографическом порядке перестановку.

Во всех приведенных ниже реализациях a — массив, в котором в прямом порядке записана перестановка, а n — количество элементов в перестановке.

C

typedef int T;

void swapItems (T *array, unsigned index_1, unsigned index_2) {
    T temp = array[index_1];
    array[index_1] = array[index_2];
    array[index_2] = temp;
}

int NarayanaNextPermutation (T *a, int n) {
    int i, j, l;
    /* Шаг № 1 */
    for (j = n - 2; j >= 0 && a[j] >= a[j + 1]; --j);
    /* Шаг № 2 */
    if (j == -1)
        return 0;
    for (l = n - 1; a[j] >= a[l]; --l);
    swapItems(a, l, j);
    ++j;
    /* Шаг № 3 */
    for (i = 0; i < (n - j + 1) >> 1; ++i)
		swapItems(a, j + i, n - i - 1);
    return j;
}

Pascal

type T = integer;

function NarayanaNextPermutation (var a: array of T; n: integer): integer;
var i, k, l: integer;
    procedure SwapItems (index_1, index_2: word);
    var temp: T;
    begin
        temp := a[index_1];
        a[index_1] := a[index_2];
        a[index_2] := temp
    end;
begin
    { Шаг № 1 }
    k := n - 2;
    while (k >= 0) and (a[k] >= a[k + 1]) do
        k := k - 1;
    if k = -1 then
        NarayanaNextPermutation := 0
    else
    begin
        { Шаг № 2 }
        l := n - 1;
        while (l >= k + 1) and (a[k] >= a[l]) do
            l := l - 1;
        SwapItems(k, l);
        { Шаг № 3 }
        for i := k + 1 to (n + k) div 2 do
        begin
            l := n + k - i;
            SwapItems(i, l)
        end;
        NarayanaNextPermutation := i
    end
end;

PHP

Вариант № 1

function NarayanaNextPermutation ($a, $n) {
    $out = $a;
    // Шаг № 1
    $k = $n - 2;
    while ($k >= 0 && $out[$k] >= $out[$k + 1]) {
	    --$k;
    }
    if (-1 == $k) {
	    return false;
    }
    // Шаг № 2
    $t = $n - 1;
    while ($t >= 0 && $t >= $k + 1 && $out[$k] >= $out[$t]) {
	    --$t;
    }
    $tmp = $out[$k];
    $out[$k] = $out[$t];
    $out[$t] = $tmp;
    // Шаг № 3
    for ($i = $k + 1; $i < ceil(($n + $k) / 2); ++$i) {
	    $t = $n + $k - $i;
	    $tmp = $out[$i];
	    $out[$i] = $out[$t];
	    $out[$t] = $tmp;
    }

    return $out;
}

Вариант № 2

Вариант с выводом справа налево:

$b = "123456789";
$a = strrev($b);
while ($a !=$b) {
    $i = 0;

    while($a[$i] > $a[$i - 1]) {
        $i++;
    }
    $j = 0;
    while($a[$j] < $a[$i]) {
        ++$j;
    }

    $c = $a[$j];
    $a[$j] = $a[$i];
    $a[$i] = $c;

    $x = strrev(substr($a, 0, $i));
    $y = substr($a, $i);

    print $a = $x . $y;
    print <br/>;
}