Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Daniel Wallin
committed
Jun 24, 2011
0 parents
commit d9fd661
Showing
9 changed files
with
522 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// SortingLib.cpp : Defines the entry point for the DLL application. | ||
// | ||
#include <iostream> | ||
#include <deque> | ||
namespace boost | ||
{ | ||
namespace detail | ||
{ | ||
template<typename T, typename Holder> | ||
class qobjclass //I use a class because only class templates can be partially specialized | ||
{ | ||
public: | ||
inline static const T& qobj(typename const Holder& a, int d) | ||
{ | ||
return a[d]; | ||
} | ||
}; | ||
template<typename T> | ||
class qobjclass<T, typename std::deque<T>::iterator>//I use a class because only class templates can be partially specialized | ||
{ | ||
public: | ||
inline static const T& qobj(typename const std::deque<T>::iterator& a, int d) | ||
{ | ||
return *(a + d); | ||
} | ||
}; | ||
//I need all of these special functions because I cannot do partial specializations for function templates, but I need the simulate it | ||
template<typename T> | ||
inline T& _get(typename T* a, int d) | ||
{ | ||
return a[d]; | ||
} | ||
template<typename T> | ||
inline T& _get(typename std::deque<T>::iterator& a, int d) | ||
{ | ||
return *(a + d); | ||
} | ||
#define qobj(a, b) qobjclass<KeyHolds, Key>::qobj((a), (b)) | ||
#define get(a, b) _get<Key>((a), (b)) | ||
template<typename KeyHolds, typename Key> | ||
void mkquicksort(typename Key* ar, int l, int r, int bit, typename const KeyHolds& term) | ||
{ | ||
if(r <= l) return; | ||
typename register Key* a = ar; | ||
register int i = l - 1, j = r, d = bit; typename const KeyHolds v = qobj(get(a, j), d);//speed increase with registers | ||
int p = i, q = j; | ||
while(i < j) | ||
{ | ||
while(qobj(get(a, ++i), d) < v) ; | ||
while(v < qobj(get(a, --j), d)) if(j == l) break; | ||
if(i > j) break; | ||
std::swap(get(a, i), get(a, j)); | ||
if(qobj(get(a, i), d) == v) {++p; std::swap(get(a, p), get(a, i));} | ||
if(qobj(get(a, j), d) == v) {--q; std::swap(get(a, q), get(a, j));} | ||
} | ||
if(p == q) | ||
{ | ||
if(!(v == term)) mkquicksort(a, l, r, d + 1, term); | ||
return; | ||
} | ||
if(qobj(get(a, i), d) < v) ++i; | ||
int k = l; | ||
for( ; k <= p; j--, k++) std::swap(get(a, k), get(a, j)); | ||
for(k = r; k >= q; i++, k--) std::swap(get(a, k), get(a, i)); | ||
mkquicksort(a, l, j, d, term); | ||
if((i == r) && (qobj(get(a, i), d) == v)) ++i; | ||
if(!(v == term)) mkquicksort(a, j + 1, i - 1, d + 1, term); | ||
mkquicksort(a, i, r, d, term); | ||
} | ||
////////////////// | ||
template<typename KeyHolds, typename Key> | ||
void rmkquicksort(typename Key* ar, int l, int r, int bit, typename const KeyHolds& term) | ||
{ | ||
if(r <= l) return; | ||
typename register Key* a = ar; | ||
register int i = l - 1, j = r, d = bit; typename const KeyHolds v = qobj(get(a, j), d);//speed increase with registers | ||
int p = i, q = j; | ||
while(i < j) | ||
{ | ||
while(v < qobj(get(a, ++i), d)) ; | ||
while(qobj(get(a, --j), d) < v) if(j == l) break; | ||
if(i > j) break; | ||
std::swap(get(a, i), get(a, j)); | ||
if(qobj(get(a, i), d) == v) {++p; std::swap(get(a, p), get(a, i));} | ||
if(qobj(get(a, j), d) == v) {--q; std::swap(get(a, q), get(a, j));} | ||
} | ||
if(p == q) | ||
{ | ||
if(!(v == term)) rmkquicksort(a, l, r, d + 1, term); | ||
return; | ||
} | ||
if(v < qobj(get(a, i), d)) ++i; | ||
int k = l; | ||
for( ; k <= p; j--, k++) std::swap(get(a, k), get(a, j)); | ||
for(k = r; k >= q; i++, k--) std::swap(get(a, k), get(a, i)); | ||
rmkquicksort(a, l, j, d, term); | ||
if((i == r) && (qobj(get(a, i), d) == v)) ++i; | ||
if(!(v == term)) rmkquicksort(a, j + 1, i - 1, d + 1, term); | ||
rmkquicksort(a, i, r, d, term); | ||
} | ||
} | ||
template<typename KeyHolds, typename Key> | ||
inline void mk_qsort(typename Key* data, int size, typename const KeyHolds term) //normal | ||
{ | ||
detail::mkquicksort<KeyHolds, Key>(data, 0, size, 0, term); | ||
} | ||
template<typename KeyHolds, typename Key> | ||
inline void r_mk_qsort(typename Key* data, int size, typename const KeyHolds term) //reverse | ||
{ | ||
detail::rmkquicksort<KeyHolds, Key>(data, 0, size, 0, term); | ||
} | ||
} | ||
#include <time.h> | ||
//can't sort these with normal quicksort but you can with multikey quicksort | ||
//these aren't real | ||
int rrr[10]; | ||
int rrr1[10]; | ||
int rrr2[10]; | ||
int rrr3[10]; | ||
//cna't sort this with normal quicksort but you can with multikey quicksort | ||
int* rrrr[4] = {rrr, rrr1, rrr2, rrr3}; | ||
void test() | ||
{ | ||
time_t repeatable = time(NULL); | ||
srand((unsigned)repeatable); | ||
for(int x = 0; x < 4; x++) | ||
{ | ||
for(int y = 0; y < 5; y++) | ||
{ | ||
rrrr[x][y] = rand() % 2; | ||
} | ||
for(int y = 5; y < 10; y++) | ||
{ | ||
rrrr[x][y] = rand() % 3; | ||
} | ||
rrrr[x][10] = 255; | ||
} | ||
cout << "Normal" << endl; | ||
boost::mk_qsort<int, int*>(rrrr, 3, 255); | ||
for(int x = 0; x < 4; x++) | ||
{ | ||
cout << endl; | ||
for(int y = 0; y < 10; y++) | ||
{ | ||
cout << rrrr[x][y] << " "; | ||
} | ||
} | ||
cout << endl << endl << "Reverse" << endl << endl; | ||
srand((unsigned)repeatable); | ||
for(int x = 0; x < 4; x++) | ||
{ | ||
for(int y = 0; y < 5; y++) | ||
{ | ||
rrrr[x][y] = rand() % 2; | ||
} | ||
for(int y = 5; y < 10; y++) | ||
{ | ||
rrrr[x][y] = rand() % 3; | ||
} | ||
rrrr[x][10] = 255; | ||
} | ||
boost::r_mk_qsort<int, int*>(rrrr, 3, 255); | ||
for(int x = 0; x < 4; x++) | ||
{ | ||
for(int y = 0; y < 10; y++) | ||
{ | ||
cout << rrrr[x][y] << " "; | ||
} | ||
cout << endl; | ||
} | ||
} | ||
int main() | ||
{ | ||
test(); | ||
return 0; | ||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// radixsort.cpp : Defines the entry point for the console application. | ||
// this program sorts the class radixtest by the numbers array contained in radixtest. | ||
//It first examines the first integer in the numbers array, then the second. | ||
//the array test of radixtests is sorted, then outputed to the standard output. | ||
//they will be in the proper order. | ||
//this could also be done by an operator< and used with std::sort | ||
//but that operator would have multiple branches | ||
//I wrote an operator< to show why it would be slow | ||
|
||
#include "radix.hpp" | ||
#include <cstdlib> | ||
#include <iostream> | ||
#include <time.h> | ||
class radixtest | ||
{ | ||
public: | ||
int numbers[5]; | ||
radixtest() | ||
{ | ||
numbers[0] = rand() % 10; | ||
numbers[1] = rand() % 10; | ||
numbers[2] = rand() % 10; | ||
numbers[3] = rand() % 10; | ||
numbers[4] = rand() % 10; | ||
} | ||
inline unsigned char operator[](int num) | ||
{return ((unsigned char*)numbers)[num];} | ||
//if this was a template class you would have to generate 20-40 | ||
//different versions of it before all the code made for this function | ||
//added up to the same amount of code generated just for one operator< | ||
//the size of code this function takes is constant and does not increase with the amount of numbers | ||
//operator< increases for each number added on | ||
inline unsigned char operator[](int num) const | ||
{return ((unsigned char*)numbers)[num];} | ||
bool operator<(const radixtest& a) const | ||
{ | ||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
//if this was a template class that was used for many different types | ||
//think of how much code bloat you would have just from this function | ||
//not to mention all of the other functions that you would have | ||
if(numbers[0] < a.numbers[0]) | ||
return true; | ||
else if(numbers[0] == a.numbers[0]) | ||
{ | ||
if (numbers[1] < a.numbers[1]) | ||
return true; | ||
else if(numbers[1] == a.numbers[1]) | ||
{ | ||
if(numbers[2] < a.numbers[2]) | ||
return true; | ||
else if(numbers[2] == a.numbers[2]) | ||
{ | ||
if(numbers[3] < a.numbers[3]) | ||
return true; | ||
else if(numbers[3] == a.numbers[3]) | ||
{ | ||
if(numbers[4] < a.numbers[4]) | ||
{ return true;} | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
}; | ||
std::ostream& operator<<(std::ostream& o, radixtest& t) | ||
{ | ||
return o << "{" << t.numbers[0] << ", " << t.numbers[1] << ", " << t.numbers[2] << ", " << t.numbers[3] << ", " << t.numbers[4] << "}"; | ||
} | ||
int main(int argc, char* argv[]) | ||
{ | ||
srand((unsigned)time(NULL)); | ||
radixtest tests[1000]; | ||
boost::radix_sort(tests, 1000); | ||
for(int x = 0; x < 999; x++) | ||
{ | ||
std::cout << tests[x] << " "; | ||
if(tests[x + 1] < tests[x]) | ||
{ | ||
cout << "ERROR" << endl; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
Oops, something went wrong.