first commit
This commit is contained in:
111
include/framework/sort/sort.h
Normal file
111
include/framework/sort/sort.h
Normal file
@ -0,0 +1,111 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSORT__
|
||||
#define __NSORT__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
#include "container/narray.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
Sort class.
|
||||
|
||||
Can sort floating point numbers using QuickSort.
|
||||
Can also sort integer numbers using Radix sort (byte-sort).
|
||||
|
||||
Use T to specify the type of value to sort and O to track a user value in
|
||||
the sorted array (for example an index into the unsorted array).
|
||||
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <typename T, typename O> struct Sort
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
struct Entry
|
||||
{
|
||||
T v;
|
||||
O o;
|
||||
};
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
static void inline SwapEntries(Entry &a, Entry &b)
|
||||
{ Entry t = a; a = b; b = t; }
|
||||
|
||||
static void RecurseQuickSort(Entry *entries, int left, int right)
|
||||
{
|
||||
if (left >= right)
|
||||
return;
|
||||
|
||||
int pivot = (left + right) >> 1;
|
||||
SwapEntries(entries[left], entries[pivot]);
|
||||
|
||||
int ls = left;
|
||||
for (int cr = left + 1; cr <= right; ++cr)
|
||||
if (entries[cr].v < entries[left].v)
|
||||
SwapEntries(entries[cr], entries[++ls]);
|
||||
|
||||
SwapEntries(entries[left], entries[ls]);
|
||||
RecurseQuickSort(entries, left, ls - 1);
|
||||
RecurseQuickSort(entries, ls + 1, right);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Quicksort n entries in-place.
|
||||
static void QuickSort(int n, Entry *entries)
|
||||
{
|
||||
RecurseQuickSort(entries, 0, n - 1);
|
||||
}
|
||||
|
||||
/// Byte-sort sort n entries from in to out.
|
||||
static Array <Entry> *ByteSort(uint n, Array <Entry> *a, Array <Entry> *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return 0;
|
||||
|
||||
uint radix[257];
|
||||
|
||||
for (size_t pass = 0; pass < sizeof(T); ++pass)
|
||||
{
|
||||
// clear radix buffer
|
||||
for (uint i = 0; i < 257; ++i)
|
||||
radix[i] = 0;
|
||||
|
||||
// count radix
|
||||
for (uint i = 0; i < n; ++i)
|
||||
++radix[uint((*a)[i].v & 255) + 1];
|
||||
|
||||
// convert count to index
|
||||
for (uint i = 0; i < 256; ++i)
|
||||
radix[i + 1] += radix[i];
|
||||
|
||||
// insert values
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
const uint p = radix[uint((*a)[i].v & 255)]++;
|
||||
(*b)[p].v = (*a)[i].v >> 8; // transfer & shift radix
|
||||
(*b)[p].o = (*a)[i].o;
|
||||
}
|
||||
|
||||
// swap arrays
|
||||
Array <Entry> *tmp = b; b = a; a = tmp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user