排序算法——全排序(Permutation sort)【代碼實現】

ActionScript

//recursively builds the permutations of permutable, appended to front, and returns the first sorted permutation it encounters
function permutations(front:Array, permutable:Array):Array {
	//If permutable has length 1, there is only one possible permutation. Check whether it's sorted
	if (permutable.length==1)
		return isSorted(front.concat(permutable));
	else
		//There are multiple possible permutations. Generate them.
		var i:uint=0,tmp:Array=null;
		do
		{
			tmp=permutations(front.concat([permutable[i]]),remove(permutable,i));
			i++;
		}while (i< permutable.length && tmp == null);
		//If tmp != null, it contains the sorted permutation. If it does not contain the sorted permutation, return null. Either way, return tmp.
		return tmp;
}
//returns the array if it's sorted, or null otherwise
function isSorted(data:Array):Array {
	for (var i:uint = 1; i < data.length; i++) 
		if (data[i]<data[i-1]) 
			return null;
	return data;
}
//returns a copy of array with the i'th element removed
function remove(array:Array, i:uint):Array {
	return array.filter(function(item,index,array){return(index !=i)}) ;
}
//wrapper around the permutation function to provide a more logical interface
function permutationSort(array:Array):Array {
	return permutations([],array);
}

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef int(*cmp_func)(const void*, const void*);
 
void perm_sort(void *a, int n, size_t msize, cmp_func _cmp)
{
	char *p, *q, *tmp = malloc(msize);
#	define A(i) ((char *)a + msize * (i))
#	define swap(a, b) {\
		memcpy(tmp, a, msize);\
		memcpy(a, b, msize);\
		memcpy(b, tmp, msize);	}
	while (1) {
		/* find largest k such that a[k - 1] < a[k] */
		for (p = A(n - 1); (void*)p > a; p = q)
			if (_cmp(q = p - msize, p) > 0)
				break;
 
		if ((void*)p <= a) break;
 
		/* find largest l such that a[l] > a[k - 1] */
		for (p = A(n - 1); p > q; p-= msize)
			if (_cmp(q, p) > 0) break;
 
		swap(p, q); /* swap a[k - 1], a[l] */
		/* flip a[k] through a[end] */
		for (q += msize, p = A(n - 1); q < p; q += msize, p -= msize)
			swap(p, q);
	}
	free(tmp);
}
 
int scmp(const void *a, const void *b) { return strcmp(*(const char *const *)a, *(const char *const *)b); }
 
int main()
{
	int i;
	const char *strs[] = { "spqr", "abc", "giant squid", "stuff", "def" };
	perm_sort(strs, 5, sizeof(*strs), scmp);
 
	for (i = 0; i < 5; i++)
		printf("%s\n", strs[i]);
	return 0;
}

C++

#include <algorithm>
 
template<typename ForwardIterator>
 void permutation_sort(ForwardIterator begin, ForwardIterator end)
{
  while (std::next_permutation(begin, end))
  {
    // -- this block intentionally left empty --
  }
}

C#

public static class PermutationSorter
{
    public static void Sort<T>(List<T> list) where T : IComparable
    {
        PermutationSort(list, 0);
    }
    public static bool PermutationSort<T>(List<T> list, int i) where T : IComparable
    {
        int j;
        if (issorted(list, i))
        {
            return true;
        }
        for (j = i + 1; j < list.Count; j++)
        {
            T temp = list[i];
            list[i] = list[j];
            list[j] = temp;
            if (PermutationSort(list, i + 1))
            {
                return true;
            }
            temp = list[i];
            list[i] = list[j];
            list[j] = temp;
        }
        return false;
    }
    public static bool issorted<T>(List<T> list, int i) where T : IComparable
    {
	    for (int j = list.Count-1; j > 0; j--)
        {
	        if(list[j].CompareTo(list[j-1])<0)
            {
		        return false;
	        }
	    }
	    return true;
    }
}

Go

package main
 
import "fmt"
 
var a = []int{170, 45, 75, -90, -802, 24, 2, 66}
 
// in place permutation sort of slice a
func main() {
    fmt.Println("before:", a)
    if len(a) > 1 && !recurse(len(a) - 1) {
        // recurse should never return false from the top level.
        // if it does, it means some code somewhere is busted,
        // either the the permutation generation code or the
        // sortedness testing code.
        panic("sorted permutation not found!")
    }
    fmt.Println("after: ", a)
}
 
// recursive permutation generator
func recurse(last int) bool {
    if last <= 0 {
        // bottom of recursion.  test if sorted.
        for i := len(a) - 1; a[i] >= a[i-1]; i-- {
            if i == 1 {
                return true
            }
        }
        return false
    }
    for i := 0; i <= last; i++ {
        a[i], a[last] = a[last], a[i]
        if recurse(last - 1) {
            return true
        }
        a[i], a[last] = a[last], a[i]
    }
    return false
}

Java

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
 
public class PermutationSort 
{
	public static void main(String[] args)
	{
		int[] a={3,2,1,8,9,4,6};
		System.out.println("Unsorted: " + Arrays.toString(a));
		a=pSort(a);
		System.out.println("Sorted: " + Arrays.toString(a));
	}
	public static int[] pSort(int[] a)
	{
		List<int[]> list=new ArrayList<int[]>();
		permute(a,a.length,list);
		for(int[] x : list)
			if(isSorted(x))
				return x;
		return a;
	}
	private static void permute(int[] a, int n, List<int[]> list) 
	{
		if (n == 1) 
		{
			int[] b=new int[a.length];
			System.arraycopy(a, 0, b, 0, a.length);
			list.add(b);
		    return;
		}
		for (int i = 0; i < n; i++) 
		{
		        swap(a, i, n-1);
		        permute(a, n-1, list);
		        swap(a, i, n-1);
		 }
	}
	private static boolean isSorted(int[] a)
	{
		for(int i=1;i<a.length;i++)
			if(a[i-1]>a[i])
				return false;
		return true;
	}
	private static void swap(int[] arr,int i, int j)
	{
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
}

Kotlin

// version 1.1.2
 
fun <T : Comparable<T>> isSorted(list: List<T>): Boolean {
    val size = list.size
    if (size < 2) return true
    for (i in 1 until size) {
        if (list[i] < list[i - 1]) return false
    }
    return true
}
 
fun <T : Comparable<T>> permute(input: List<T>): List<List<T>> {
    if (input.size == 1) return listOf(input)
    val perms = mutableListOf<List<T>>()
    val toInsert = input[0]
    for (perm in permute(input.drop(1))) {
        for (i in 0..perm.size) {
            val newPerm = perm.toMutableList()
            newPerm.add(i, toInsert)
            perms.add(newPerm)
        }
    }
    return perms
}
 
fun <T : Comparable<T>> permutationSort(input: List<T>): List<T> {
    if (input.size == 1) return input
    val toInsert = input[0]
    for (perm in permute(input.drop(1))) {
        for (i in 0..perm.size) {
            val newPerm = perm.toMutableList()
            newPerm.add(i, toInsert)
            if (isSorted(newPerm)) return newPerm
        }
    }
    return input
}
 
fun main(args: Array<String>) {
    val input = listOf('d', 'b', 'e', 'a', 'f', 'c')
    println("Before sorting : $input")
    val output = permutationSort(input)
    println("After sorting  : $output")
    println()
    val input2 = listOf("first", "second", "third", "fourth", "fifth", "sixth")
    println("Before sorting : $input2")
    val output2 = permutationSort(input2)
    println("After sorting  : $output2")
}

Perl

sub psort {
        my ($x, $d) = @_;
 
        unless ($d //= $#$x) {
                $x->[$_] < $x->[$_ - 1] and return for 1 .. $#$x;
                return 1
        }
 
        for (0 .. $d) {
                unshift @$x, splice @$x, $d, 1;
                next if $x->[$d] < $x->[$d - 1];
                return 1 if psort($x, $d - 1);
        }
}
 
my @a = map+(int rand 100), 0 .. 10;
print "Before:\t@a\n";
psort(\@a);
print "After:\t@a\n"

Perl 6

# Lexicographic permuter from "Permutations" task.
sub next_perm ( @a ) {
    my $j = @a.end - 1;
    $j-- while $j >= 1 and [>] @a[ $j, $j+1 ];
 
    my $aj = @a[$j];
    my $k  = @a.end;
    $k-- while [>] $aj, @a[$k];
 
    @a[ $j, $k ] .= reverse;
 
    my Int $r = @a.end;
    my Int $s = $j + 1;
    while $r > $s {
        @a[ $r, $s ] .= reverse;
        $r--;
        $s++;
    }
}
 
sub permutation_sort ( @a ) {
    my @n = @a.keys;
    my $perm_count = [*] 1 .. +@n; # Factorial
    for ^$perm_count {
        my @permuted_a = @a[ @n ];
        return @permuted_a if [le] @permuted_a;
        next_perm(@n);
    }
}
 
my @data  = < c b e d a >; # Halfway between abcde and edcba
say 'Input  = ' ~ @data;
say 'Output = ' ~ @data.&permutation_sort;

PHP

function inOrder($arr){
	for($i=0;$i<count($arr);$i++){
		if(isset($arr[$i+1])){
			if($arr[$i] > $arr[$i+1]){
				return false;
			}
		}
	}
	return true;
}
 
function permute($items, $perms = array( )) {
    if (empty($items)) {
		if(inOrder($perms)){
			return $perms;
		}
    }  else {
        for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
             list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             $res = permute($newitems, $newperms);
			 if($res){
				return $res;
			 }		 		 
         }
    }
}
 
$arr = array( 8, 3, 10, 6, 1, 9, 7, 2, 5, 4);
$arr = permute($arr);
echo implode(',',$arr);

PowerShell

Function PermutationSort( [Object[]] $indata, $index = 0, $k = 0 )
{
	$data = $indata.Clone()
	$datal = $data.length - 1
	if( $datal -gt 0 ) {
		for( $j = $index; $j -lt $datal; $j++ )
		{
			$sorted = ( PermutationSort $data ( $index + 1 ) $j )[0]
			if( -not $sorted )
			{
				$temp = $data[ $index ]
				$data[ $index ] = $data[ $j + 1 ]
				$data[ $j + 1 ] = $temp
			}
		}
		if( $index -lt ( $datal - 1 ) )
		{
			PermutationSort $data ( $index + 1 ) $j
		} else {
			$sorted = $true
			for( $i = 0; ( $i -lt $datal ) -and $sorted; $i++ )
			{
				$sorted = ( $data[ $i ] -le $data[ $i + 1 ] )
			}
			$sorted
			$data
		}
	}
}
 
0..4 | ForEach-Object { $a = $_; 0..4 | Where-Object { -not ( $_ -match "$a" ) } |
	ForEach-Object { $b = $_; 0..4 | Where-Object { -not ( $_ -match "$a|$b" ) } |
		ForEach-Object { $c = $_; 0..4 | Where-Object { -not ( $_ -match "$a|$b|$c" ) } |
			ForEach-Object { $d = $_; 0..4 | Where-Object { -not ( $_ -match "$a|$b|$c|$d" ) } |
				ForEach-Object { $e=$_; "$( PermutationSort ( $a, $b, $c, $d, $e ) )" } 
			} 
		} 
	} 
}
$l = 8; PermutationSort ( 1..$l | ForEach-Object { $Rand = New-Object Random }{ $Rand.Next( 0, $l - 1 ) } )

Python

from itertools import permutations
 
in_order = lambda s: all(x <= s[i+1] for i,x in enumerate(s[:-1]))
perm_sort = lambda s: (p for p in permutations(s) if in_order(p)).next()

Ruby

class Array
  def permutationsort
    permutation.each{|perm| return perm if perm.sorted?}
  end
 
  def sorted?
    each_cons(2).all? {|a, b| a <= b}
  end
end

更多代碼,敬請期待!
整理自網絡。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章