C
#include<stdlib.h>
#include<stdio.h>
int* patienceSort(int* arr,int size){
int decks[size][size],i,j,min,pickedRow;
int *count = (int*)calloc(sizeof(int),size),*sortedArr = (int*)malloc(size*sizeof(int));
for(i=0;i<size;i++){
for(j=0;j<size;j++){
if(count[j]==0 || (count[j]>0 && decks[j][count[j]-1]>=arr[i])){
decks[j][count[j]] = arr[i];
count[j]++;
break;
}
}
}
min = decks[0][count[0]-1];
pickedRow = 0;
for(i=0;i<size;i++){
for(j=0;j<size;j++){
if(count[j]>0 && decks[j][count[j]-1]<min){
min = decks[j][count[j]-1];
pickedRow = j;
}
}
sortedArr[i] = min;
count[pickedRow]--;
for(j=0;j<size;j++)
if(count[j]>0){
min = decks[j][count[j]-1];
pickedRow = j;
break;
}
}
free(count);
free(decks);
return sortedArr;
}
int main(int argC,char* argV[])
{
int *arr, *sortedArr, i;
if(argC==0)
printf("Usage : %s <integers to be sorted separated by space>");
else{
arr = (int*)malloc((argC-1)*sizeof(int));
for(i=1;i<=argC;i++)
arr[i-1] = atoi(argV[i]);
sortedArr = patienceSort(arr,argC-1);
for(i=0;i<argC-1;i++)
printf("%d ",sortedArr[i]);
}
return 0;
}
C++
#include <iostream>
#include <vector>
#include <stack>
#include <iterator>
#include <algorithm>
#include <cassert>
template <class E>
struct pile_less {
bool operator()(const std::stack<E> &pile1, const std::stack<E> &pile2) const {
return pile1.top() < pile2.top();
}
};
template <class E>
struct pile_greater {
bool operator()(const std::stack<E> &pile1, const std::stack<E> &pile2) const {
return pile1.top() > pile2.top();
}
};
template <class Iterator>
void patience_sort(Iterator first, Iterator last) {
typedef typename std::iterator_traits<Iterator>::value_type E;
typedef std::stack<E> Pile;
std::vector<Pile> piles;
// sort into piles
for (Iterator it = first; it != last; it++) {
E& x = *it;
Pile newPile;
newPile.push(x);
typename std::vector<Pile>::iterator i =
std::lower_bound(piles.begin(), piles.end(), newPile, pile_less<E>());
if (i != piles.end())
i->push(x);
else
piles.push_back(newPile);
}
// priority queue allows us to merge piles efficiently
// we use greater-than comparator for min-heap
std::make_heap(piles.begin(), piles.end(), pile_greater<E>());
for (Iterator it = first; it != last; it++) {
std::pop_heap(piles.begin(), piles.end(), pile_greater<E>());
Pile &smallPile = piles.back();
*it = smallPile.top();
smallPile.pop();
if (smallPile.empty())
piles.pop_back();
else
std::push_heap(piles.begin(), piles.end(), pile_greater<E>());
}
assert(piles.empty());
}
int main() {
int a[] = {4, 65, 2, -31, 0, 99, 83, 782, 1};
patience_sort(a, a+sizeof(a)/sizeof(*a));
std::copy(a, a+sizeof(a)/sizeof(*a), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
return 0;
}
Go
package main
import (
"fmt"
"container/heap"
"sort"
)
type IntPile []int
func (self IntPile) Top() int { return self[len(self)-1] }
func (self *IntPile) Pop() int {
x := (*self)[len(*self)-1]
*self = (*self)[:len(*self)-1]
return x
}
type IntPilesHeap []IntPile
func (self IntPilesHeap) Len() int { return len(self) }
func (self IntPilesHeap) Less(i, j int) bool { return self[i].Top() < self[j].Top() }
func (self IntPilesHeap) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
func (self *IntPilesHeap) Push(x interface{}) { *self = append(*self, x.(IntPile)) }
func (self *IntPilesHeap) Pop() interface{} {
x := (*self)[len(*self)-1]
*self = (*self)[:len(*self)-1]
return x
}
func patience_sort (n []int) {
var piles []IntPile
// sort into piles
for _, x := range n {
j := sort.Search(len(piles), func (i int) bool { return piles[i].Top() >= x })
if j != len(piles) {
piles[j] = append(piles[j], x)
} else {
piles = append(piles, IntPile{ x })
}
}
// priority queue allows us to merge piles efficiently
hp := IntPilesHeap(piles)
heap.Init(&hp)
for i, _ := range n {
smallPile := heap.Pop(&hp).(IntPile)
n[i] = smallPile.Pop()
if len(smallPile) != 0 {
heap.Push(&hp, smallPile)
}
}
if len(hp) != 0 {
panic("something went wrong")
}
}
func main() {
a := []int{4, 65, 2, -31, 0, 99, 83, 782, 1}
patience_sort(a)
fmt.Println(a)
}
Java
import java.util.*;
public class PatienceSort {
public static <E extends Comparable<? super E>> void sort (E[] n) {
List<Pile<E>> piles = new ArrayList<Pile<E>>();
// sort into piles
for (E x : n) {
Pile<E> newPile = new Pile<E>();
newPile.push(x);
int i = Collections.binarySearch(piles, newPile);
if (i < 0) i = ~i;
if (i != piles.size())
piles.get(i).push(x);
else
piles.add(newPile);
}
// priority queue allows us to retrieve least pile efficiently
PriorityQueue<Pile<E>> heap = new PriorityQueue<Pile<E>>(piles);
for (int c = 0; c < n.length; c++) {
Pile<E> smallPile = heap.poll();
n[c] = smallPile.pop();
if (!smallPile.isEmpty())
heap.offer(smallPile);
}
assert(heap.isEmpty());
}
private static class Pile<E extends Comparable<? super E>> extends Stack<E> implements Comparable<Pile<E>> {
public int compareTo(Pile<E> y) { return peek().compareTo(y.peek()); }
}
public static void main(String[] args) {
Integer[] a = {4, 65, 2, -31, 0, 99, 83, 782, 1};
sort(a);
System.out.println(Arrays.toString(a));
}
}
Kotlin
// version 1.1.2
fun <T : Comparable<T>> patienceSort(arr: Array<T>) {
if (arr.size < 2) return
val piles = mutableListOf<MutableList<T>>()
outer@ for (el in arr) {
for (pile in piles) {
if (pile.last() > el) {
pile.add(el)
continue@outer
}
}
piles.add(mutableListOf(el))
}
for (i in 0 until arr.size) {
var min = piles[0].last()
var minPileIndex = 0
for (j in 1 until piles.size) {
if (piles[j].last() < min) {
min = piles[j].last()
minPileIndex = j
}
}
arr[i] = min
val minPile = piles[minPileIndex]
minPile.removeAt(minPile.lastIndex)
if (minPile.size == 0) piles.removeAt(minPileIndex)
}
}
fun main(args: Array<String>) {
val iArr = arrayOf(4, 65, 2, -31, 0, 99, 83, 782, 1)
patienceSort(iArr)
println(iArr.contentToString())
val cArr = arrayOf('n', 'o', 'n', 'z', 'e', 'r', 'o', 's', 'u','m')
patienceSort(cArr)
println(cArr.contentToString())
val sArr = arrayOf("dog", "cow", "cat", "ape", "ant", "man", "pig", "ass", "gnu")
patienceSort(sArr)
println(sArr.contentToString())
}
Perl
sub patience_sort {
my @s = [shift];
for my $card (@_) {
my @t = grep { $_->[-1] > $card } @s;
if (@t) { push @{shift(@t)}, $card }
else { push @s, [$card] }
}
my @u;
while (my @v = grep @$_, @s) {
my $value = (my $min = shift @v)->[-1];
for (@v) {
($min, $value) =
($_, $_->[-1]) if $_->[-1] < $value
}
push @u, pop @$min;
}
return @u
}
print join ' ', patience_sort qw(4 3 6 2 -1 13 12 9);
Perl 6
multi patience(*@deck) {
my @stacks;
for @deck -> $card {
with @stacks.first: $card before *[*-1] -> $stack {
$stack.push: $card;
}
else {
@stacks.push: [$card];
}
}
gather while @stacks {
take .pop given min :by(*[*-1]), @stacks;
@stacks .= grep: +*;
}
}
say ~patience ^10 . pick(*);
PHP
<?php
class PilesHeap extends SplMinHeap {
public function compare($pile1, $pile2) {
return parent::compare($pile1->top(), $pile2->top());
}
}
function patience_sort(&$n) {
$piles = array();
// sort into piles
foreach ($n as $x) {
// binary search
$low = 0; $high = count($piles)-1;
while ($low <= $high) {
$mid = (int)(($low + $high) / 2);
if ($piles[$mid]->top() >= $x)
$high = $mid - 1;
else
$low = $mid + 1;
}
$i = $low;
if ($i == count($piles))
$piles[] = new SplStack();
$piles[$i]->push($x);
}
// priority queue allows us to merge piles efficiently
$heap = new PilesHeap();
foreach ($piles as $pile)
$heap->insert($pile);
for ($c = 0; $c < count($n); $c++) {
$smallPile = $heap->extract();
$n[$c] = $smallPile->pop();
if (!$smallPile->isEmpty())
$heap->insert($smallPile);
}
assert($heap->isEmpty());
}
$a = array(4, 65, 2, -31, 0, 99, 83, 782, 1);
patience_sort($a);
print_r($a);
?>
Python
from functools import total_ordering
from bisect import bisect_left
from heapq import merge
@total_ordering
class Pile(list):
def __lt__(self, other): return self[-1] < other[-1]
def __eq__(self, other): return self[-1] == other[-1]
def patience_sort(n):
piles = []
# sort into piles
for x in n:
new_pile = Pile([x])
i = bisect_left(piles, new_pile)
if i != len(piles):
piles[i].append(x)
else:
piles.append(new_pile)
# use a heap-based merge to merge piles efficiently
n[:] = merge(*[reversed(pile) for pile in piles])
if __name__ == "__main__":
a = [4, 65, 2, -31, 0, 99, 83, 782, 1]
patience_sort(a)
print a
Ruby
class Array
def patience_sort
piles = []
each do |i|
if (idx = piles.index{|pile| pile.last <= i})
piles[idx] << i
else
piles << [i] #create a new pile
end
end
# merge piles
result = []
until piles.empty?
first = piles.map(&:first)
idx = first.index(first.min)
result << piles[idx].shift
piles.delete_at(idx) if piles[idx].empty?
end
result
end
end
a = [4, 65, 2, -31, 0, 99, 83, 782, 1]
p a.patience_sort
更多代码,持续更新!
整理自网络。