您的位置:首页 > 其它

模板化的七种排序算法,适用于T* vector<T>以及list<T>

2015-06-19 22:51 369 查看
  最近在写一些数据结构以及算法相关的代码,比如常用排序算法以及具有启发能力的智能算法。为了能够让写下的代码下次还能够被复用,直接将代码编写成类模板成员函数的方式,之所以没有将这种方式改成更方便的函数模板纯属于偷懒,更方便于测试代码的有效性,等代码写完也懒得去改了。下面开始介绍这段代码,有什么不对的地方欢迎前来指正。

  一共写了七种排序,插入排序InsertSort、堆排序HeapSort、快速排序QuickSort、合并排序MergeSort,计数排序CountingSort,基数排序RadixSort,桶排序BucketSort。排序思想都是根据<<Introduction to Algorithms>>而来的,所以对于这本书里面的时间复杂度都是严格遵从的,本文就不详细介绍这些算法的思想和实现机制了。针对于这七种排序,先写一个非特化的模板类Sort空着,是为了能够让模板的特化正确通过编译,接着写三个特化版本的Sort类,三个特化的版本分别接受T* vector<T>以及list<T>作为模板形参,而其中的各个成员函数接受的参数也是这些类型。函数体没有写的情况大致如下:

template<typename T>
class Sort
{

};

template<typename T>
class Sort<T*>
{
public:
void InsertSort(T* t, int length = 0)
{
}

//the hardest part is to judge the correctness
void MergeSort(T* t, int length = 0)
{
}

void HeapSort(T* t, int length = 0)
{
}

void QuickSort(T* t, int length = 0)
{
}

void CountingSort(T* t, int length = 0)
{
}

void RadixSort(T* t, int length = 0)
{
}

void BucketSort(T* t, int length = 0)
{
}

template<typename T>
class Sort<std::vector<T>>
{
public:
void InsertSort(std::vector<T>& t)
{
}

void HeapSort(std::vector<T>& t)
{
}

void QuickSort(std::vector<T>& t)
{
}

void CountingSort(std::vector<T>&t)
{
}

void RadixSort(std::vector<T>& t)
{
}

void BucketSort(std::vector<T>& t)
{
}
};

template<typename T>
class Sort<std::list<T>>
{
public:
void InsertSort(std::list<T>& t)
{
}

void MergeSort(std::list<T>& t)
{
}

void HeapSort(std::list<T>& t)
{
}

void QuickSort(std::list<T>& t)
{
}

void CountingSort(std::list<T>& t)
{
}

void RadixSort(std::list<T>& t)
{
}

void BucketSort(std::list<T>& t)
{
}

};


  对于编译期决定的类型T,基本数据类型之外,用户提供的自定义类只要重载了operator> operator< operator==...就能够直接使用这些函数。这是c++语言的特性,因为实现过程中使用了>和<来比较T,因此这个是需要的。对于T*版本的特化,因为数组本身就是通过下标运算来取得每个元素的,所以template<> Sort<T*>{}中的函数接受一个T类型指针和这个T类型数组的长度作为参数。

  由于vector这个容器的是一段连续分配的地址(如果想了解的童鞋可以去看看STL源码剖析),因此vector重载了operator[]以及operator+, operator- 这些可以直接根据index索引到目标地址的对象。这样一来template<> Sort<std::vector<T>>{}中七种排序函数都可以跟template<> Sort<T*>{}中的函数几乎一模一样,可以直接通过operator[]来获取元素。但是从最开始我是希望编写可复用的程序的,因此效率问题在我的首要考虑范围之内。因为vector的operator[]一样也是通过iterator来获取元素的,所以在Sort类中首先尝试了直接使用iterator来取得元素,在Sort<vector<T>>中的InsertSort就是这样来实现的,从代码的可读性方面来说要差点。

  而对于list容器来说,本身就是链式动态分配的内存,没有提供operator[]和operator+,operator-也是正常的,因此在Sort<list<T>>的函数实现中,没有办法使用t[i]这样的语法,因此针对list<T>的函数,一点也没有偷懒,都是使用iterator来实现的,与使用operator[]不同之处主要在于该iterator不能直接加上一个值,另一个就是iterator的边界条件比较麻烦,在iterator等于list的bigin()或者end()的时候,是不能够使用iterator--或者iterator++的,否则会触发list的断言。InsertSort算法的三种如下所示:

#include <vector>
#include <iostream>
#include <list>
#include <exception>
#include <iterator>
#include <math.h>

template<typename T>
class Sort
{

};

template<typename T>
class Sort<T*>
{
public:
void InsertSort(T* t, int length = 0)
{
if (t == NULL)
{
std::cout << "are you fucking kidding me?";
}
else
{
//<<introduction to algorithm>> the array is from 1, we are from 0
for (int i = 1; i<length; i++)
{
T temp = t[i];
int j = i - 1;
while (j >= 0 && t[j]>temp)
{
t[j + 1] = t[j];
--j;
}
t[j + 1] = temp;
}
}
}
};

#pragma region std::vector<T>
template<typename T>
class Sort<std::vector<T>>
{
public:
typedef typename std::vector<T>::iterator iterator;
public:
//actually vector use the operator[] should be faster
//the operator[] also used iterator
void InsertSort(std::vector<T>& t)
{
if (t.size()>0)
{
for (std::vector<T>::iterator it = t.begin() + 1; it != t.end(); it++)
{
std::vector<T>::iterator itFront = it - 1;
T temp = *(it);

while (*itFront > temp)
{
std::vector<T>::iterator itTemp = itFront;
itTemp++;
*itTemp = *itFront;
if (itFront != t.begin())
{
itFront--;
if (itFront == t.begin() && *itFront < temp)
{
itFront++;
break;
}
}
else
{
break;
}
}
*(itFront) = temp;
}
}
}
};
#pragma endregion

#pragma region std::list<T>
template<typename T>
class Sort<std::list<T>>
{
//for the list, we can't directly use the operator+/-,because it is the list
//actually we can use the operator[] to change it, does list solved the problem?
//not effective at all
//we should support a method to increase or decrease the pointer(iterator)!
typedef typename std::list<T>::iterator iterator;

public:
void InsertSort(std::list<T>& t)
{
for (std::list<T>::iterator it = t.begin(); it != t.end(); it++)
{
std::list<T>::iterator itFront = it;
if (++it == t.end())
{
break;
}
T temp = *it;
it--;

while (*itFront > temp)
{
std::list<T>::iterator itTemp = itFront;
itTemp++;
*itTemp = *itFront;
if (itFront != t.begin())
{
itFront--;
if (itFront == t.begin() && *itFront < temp)
{
itFront++;
break;
}
}
else
{
break;
}
}
*itFront = temp;
}
}

};

#pragma endregion


  除了InsertSort之外的所有排序Sort<vector<T>>基本上都与T*相类似,而Sort<list<T>>则必须使用iteraotr来搞定。由于InsertSort是比较简单的插入排序,其效率也不是很高。除了这一种比较排序之外,还写了MergeSort,HeapSort以及QuickSort这三种比较算法。其中MergeSort和QuickSort都使用了分治的策略。而HeapSort则充分利用了数据结构来改善排序过程。这些思想在<<Introduction to Algrithms>>都十分详细。

  除了上面的比较排序除外,还写了三种线性时间排序算法:CountingSort,RadixSort和BucketSort。这三种算法都是有其局限性的,因为CountingSort是通过输入数组的值来建立对应的计数数组,然后算出每个数对应的位置,因此输入数组的值必须是int类型才行,甚至还必须要是正数。同样的问题在RadixSort算法中也是存在的,而本模板稍微做了两点优化:一是使用c++的RTTI机制中的typeid方法来判断类型,只有是int类型才有下一步。二是解决CountingSort和RadixSort的负数和值过大过小问题,采用的方法是分割开正数和负数,针对不同类型的数再取其最大最小值,将最小值映射到0,而将最大值映射到max-min。就搞定了这个问题,稍微优化了一点空间。

  对于BucketSort算法来说,完全利用的是数据结构的技巧来取得优势,三种特化的模板都是使用vector数组来实现的,本来是想要用双端链表来搞定的,这样效率高点,但是由于没有写针对于双端链表的sort算法,所以偷了回懒,直接用vector来搞定。这个算法也是最短的算法,思想也是最简单的。对于BucketSort算法的短板,就是搞不定除了基本数据类型之外的数据,因为还需要客户重载operator/,这个就比较麻烦了,估计很少有这个需求的用户类。

  下面则是全部的代码:

点击下载代码

#include <vector>
#include <iostream>
#include <list>
#include <exception>
#include <iterator>
#include <math.h>

template<typename T>
class Sort
{

};

template<typename T>
class Sort<T*>
{
public:
void InsertSort(T* t, int length = 0)
{
if (t == NULL)
{
std::cout << "are you fucking kidding me?";
}
else
{
//<<introduction to algorithm>> the array is from 1, we are from 0
for (int i = 1; i<length; i++)
{
T temp = t[i];
int j = i - 1;
while (j >= 0 && t[j]>temp)
{
t[j + 1] = t[j];
--j;
}
t[j + 1] = temp;
}
}
}

//the hardest part is to judge the correctness
void MergeSort(T* t, int length = 0)
{
_MergeSort(t, 0, length - 1);
}

void HeapSort(T* t, int length = 0)
{
try
{
if (length>0)
{
length = length - 1;
BuildHeap(t, length);
for (int i = length; i >= 0; i--)
{
T temp = t[0];
t[0] = t[i];
t[i] = temp;
Max_Heapify(t, 0, i - 1);
}
}
}
catch (std::out_of_range e)
{
std::cout << "out_of_range error" << std::endl;
}
}

void QuickSort(T* t, int length = 0)
{
_QuickSort(t, 0, length-1);
}

//this one can only work in integer, negetive value is also included
void CountingSort(T* t, int length = 0)
{
if (typeid(T) == typeid(int))
{
//one iterator to check the min, max, the number of negetive value
int count = 0;
T* negetiveArray;
T* positiveArray;
//前一版本将比较的次数缩减到了3(n-2)/2次,但是行数太多
for (int i = 0; i < length; i++)
{
if (t[i] < 0)
{
count++;
}
}
negetiveArray = new T[count];
positiveArray = new T[length - count];
//split the array into the postive and negetive value arrays
for (int i = 0, m = 0, n = 0; i < length; i++)
{
if (t[i] < 0)
{
negetiveArray[m] = t[i];
m++;
}
else
{
positiveArray
= t[i];
n++;
}
}
T poMin = positiveArray[0], poMax = positiveArray[0];
T neMin = negetiveArray[0], neMax = negetiveArray[0];
for (int i = 0; i < count; i++)
{
if (negetiveArray[i] < neMin)
{
neMin = negetiveArray[i];
}
if (negetiveArray[i] > neMax)
{
neMax = negetiveArray[i];
}
}
for (int i = 0; i < length - count; i++)
{
if (positiveArray[i] < poMin)
{
poMin = positiveArray[i];
}
if (positiveArray[i] > poMax)
{
poMax = positiveArray[i];
}
}
//得到正负两个数组各自的最小最大差 并将两个数组映射到0-poMin;
T poMinux = poMax - poMin;
T neMinux = neMax - neMin;

T* positiveArrayed = new T[length - count];
int* countArray = new int[poMinux + 1];
memset(countArray, 0, (poMinux + 1)*sizeof(T));

for (int i = 0; i < length - count; i++)
{
countArray[positiveArray[i] - poMin] ++;
//std::cout << countArray[i] << " ";
}
//此处与算法描述中不同的地方在于,countArray用于保存每个数存在的位置,但是该位置应该是从0开始的
for (int i = 1; i <= poMinux; i++)
{
//std::cout << countArray[i - 1] << " ";
countArray[i] = countArray[i] + countArray[i - 1];
countArray[i - 1]--;
}
countArray[poMinux]--;
//将正数数组从后往前每一个数放到应该放的地方,之所以是从后往前是为了保持算法的稳定性
for (int i = length - count - 1; i >= 0; i--)
{
positiveArrayed[countArray[positiveArray[i] - poMin]] = positiveArray[i];
countArray[positiveArray[i] - poMin]--;
}

//负值数组开始的地方
T* negetiveArrayed = new T[count];
int* countArrayNe = new int[neMinux + 1];
memset(countArrayNe, 0, (neMinux + 1)*sizeof(T));

for (int i = 0; i < count; i++)
{
countArrayNe[negetiveArray[i] - neMin]++;
}
for (int i = 1; i <= neMinux; i++)
{
countArrayNe[i] += countArrayNe[i - 1];
countArrayNe[i - 1]--;
}
countArrayNe[neMinux]--;

for (int i = count - 1; i >= 0; i--)
{
negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i];
countArrayNe[negetiveArray[i] - neMin]--;
}

//正负两个数组合并
for (int i = 0, j = 0; i < length; i++)
{
if (i < count)
{
t[i] = negetiveArrayed[i];
}
else
{
t[i] = positiveArrayed[j];
j++;
}
}

delete[] negetiveArray;
delete[] positiveArray;
delete[] countArray;
delete[] countArrayNe;
delete[] negetiveArrayed;
delete[] positiveArrayed;
}
else
{
std::cout << "you are using non-int type array for Counting Sort" << std::endl;
}
}

void RadixSort(T* t, int length = 0)
{
int count = 0;
for (int i = 0; i < length; i++)
{
if (t[i] < 0)
{
count++;
}
}
T* positiveArray = new T[length - count];
T* negetiveArray = new T[count];

for (int i = 0, m=0, n=0; i < length; i++)
{
if (t[i] < 0)
{
negetiveArray[m] = -t[i];
m++;
}
else
{
positiveArray
= t[i];
n++;
}
}
_RadixSort(positiveArray, length - count);
_RadixSort(negetiveArray, count);
for (int i = 0, m=count-1, n =0; i < length; i++)
{
if (i < count)
{
t[i] = -negetiveArray[m];
m--;
}
else
{
t[i] = positiveArray
;
n++;
}
}
}

void BucketSort(T* t, int length = 0)
{
/*
this one does't like other linear time sorting, the basic type are all received for the parameter
and the class which supports operator[], operator - and operator > (< == ...).
*/
//if we achieve the algrithm with T*, it will need more time and space to judge the length of array's array
//struct, vector, list are all useful. this one is using the data structrue to decrease time;

/*
The first version is using struct to construct the bucket, then i found that i did't finish the sort for the
linked list (sort by the pointer of a linked list)
*/

T max = t[0], min = t[0];
for (int i = 0; i < length; i++)
{
if (t[i]>max)
{
max = t[i];
}
if (t[i] < min)
{
min = t[i];
}
}
int minux = max - min +1;
//std::vector<std::vector<T>> colArray;
std::vector<T>* colArray = new std::vector<T>[length];
//std::vector<T> rawArray;
for (int i = 0; i < length; i++)
{
int index = (t[i] - min)*length / minux;
std::vector<T> & rawArray = colArray[index];
rawArray.push_back(t[i]);
}
for (int i = 0; i < length; i++)
{
std::vector<T>& rawArray = colArray[i];
Sort<std::vector<T>>::InsertSort(rawArray);
}
for (int i = 0, index=0; i < length; i++)
{
std::vector<T> & rawArray = colArray[i];
//int j = 0;
for (std::vector<T>::iterator it = rawArray.begin(); it != rawArray.end(); it++)
{
t[index] = *it;
index++;
}
}
delete[] colArray;
}

private:
void _MergeSort(T* t, int a, int b)
{
if (a<b)
{
int c = (a + b) / 2;
_MergeSort(t, a, c);
_MergeSort(t, c + 1, b);
Merge(t, a, c, b);
}
}

void Merge(T* t, int a, int c, int b)
{
int n1 = c - a + 1;
int n2 = b - c;
//here to create the array dynamicly, remember to delete it;
T* temp1 = new T[n1 + 1];
T* temp2 = new T[n2 + 1];

for (int i = 0; i<n1; i++)
{
temp1[i] = t[a + i];
}
//the biggest value of positive int
temp1[n1] = 2147483647;
for (int i = 0; i<n2; i++)
{
temp2[i] = t[c + 1 + i];
}
temp2[n2] = 2147483647;

int m = 0, n = 0;
for (int i = a; i <= b; i++)
{
if (temp1[m] <= temp2
)
{
t[i] = temp1[m];
m++;
}
else if (temp1[m]>temp2
)
{
t[i] = temp2
;
n++;
}
}
//remember to clean it
delete[] temp1;
delete[] temp2;
}

//i-root re-heap;
//abstract from the tree, but did not used tree;
void Max_Heapify(T* t, int i, int length)
{
int largest = 0;
int l = GetLeftChild(i);
int r = GetRightChild(i);

if (l <= length && t[i] <t[l])
{
largest = l;
}
else
{
largest = i;
}

if (r <= length && t[largest] < t[r])
{
largest = r;
}

if (largest != i)
{
T temp = t[i];
t[i] = t[largest];
t[largest] = temp;
Max_Heapify(t, largest, length);
}
}

inline int GetLeftChild(int i)
{
return ((i + 1) << 1) - 1;
}

inline int GetRightChild(int i)
{
return (i + 1) << 1;
}

void BuildHeap(T* t, int length)
{
//after the length/2, then it should not be the tree node
for (int i = length / 2; i >= 0; i--)
{
Max_Heapify(t, i, length);
}
}

void _QuickSort(T* t, int a, int b)
{
if (a<b)
{
int s = Partition(t, a, b);
_QuickSort(t, a, s-1);
_QuickSort(t, s + 1, b);
}
}

int Partition(T* t, int a, int b)
{
T split = t[a];
//when the a equals b, a should be the split!
while (a < b)
{
while (t[b] >= split && a < b)
{
b--;
}
T temp = t[a];
t[a] = t[b];
t[b] = temp;

while (t[a] <= split && a < b)
{
a++;
}
temp = t[a];
t[a] = t[b];
t[b] = temp;
}
return a;
}

//get the index's number of t
inline int GetNIndex(int t, int i)
{
return (t%(int)pow(10, i + 1) - t%(int)pow(10, i))/pow(10,i);
}

int* GetAllIndex(int t, int count)
{
int* array = new int[count];
memset(array, 0, count*sizeof(int));
int i = 0, sum = 0;
while (t / pow(10, i) > 0)
{
int temp = t%pow(10, i + 1) - sum;
sum += array[i];
array[i] = temp / pow(10, i);
i++;
}
return array;
}

void _RadixSort(T* t, int length = 0)
{
//对于多位数来说是count位数, 而对于扑克牌问题来说就是面值和花色了
T max = t[0];
for (int i = 0; i < length; i++)
{
if (max < t[i])
{
max = t[i];
}
}
int count = 0;
//get the radix of max value;
int k = max / pow(10, count);
while (k != 0)
{
count++;
k = max / pow(10, count);
}
//int* array = new int[length*(count-1)];
//memset(array, 0, length*(count - 1)*sizeof(int));

int* positionArray = new int[length];
T* tempArray = new T[length];
//*************************************************
//change the codes more general for the problem of multi-decision sort
//using counting sort to solve every single problem;
for (int i = 0; i < count; i++)
{
int* countArray = new int[10];
memset(countArray, 0, 10 * sizeof(10));

for (int j = 0; j < length; j++)
{
positionArray[j] = GetNIndex(t[j], i);
}
//the t is changing with positionArray;
for (int m = 0; m < length; m++)
{
countArray[positionArray[m]]++;
}
for (int m = 1; m < 10; m++)
{
countArray[m] += countArray[m - 1];
countArray[m - 1]--;
}
countArray[9]--;

for (int m = length - 1; m >= 0; m--)
{
//无论其他怎么改变 位置都是相对的 positionArray[m]就是t[m]
tempArray[countArray[positionArray[m]]] = t[m];
countArray[positionArray[m]]--;
}
for (int m = 0; m < length; m++)
{
t[m] = tempArray[m];
}
delete[] countArray;
}

delete[] positionArray;
delete[] tempArray;
}
};

#pragma region std::vector<T>
template<typename T>
class Sort<std::vector<T>>
{
public:
typedef typename std::vector<T>::iterator iterator;
public:
//actually vector use the operator[] should be faster
//the operator[] also used iterator
void InsertSort(std::vector<T>& t)
{
if (t.size()>0)
{
for (std::vector<T>::iterator it = t.begin() + 1; it != t.end(); it++)
{
std::vector<T>::iterator itFront = it - 1;
T temp = *(it);

while (*itFront > temp)
{
std::vector<T>::iterator itTemp = itFront;
itTemp++;
*itTemp = *itFront;
if (itFront != t.begin())
{
itFront--;
if (itFront == t.begin() && *itFront < temp)
{
itFront++;
break;
}
}
else
{
break;
}
}
*(itFront) = temp;
}
}
}

void MergeSort(std::vector<T>& t)
{
int length = t.size();
if (length <= 1)
{
return;
}
else
{
_MergeSort(t, 0, length - 1);
}
}

void HeapSort(std::vector<T>& t)
{
int length = t.size();
try
{
if (length>0)
{
length = length - 1;
BuildHeap(t, length);
for (int i = length; i >= 0; i--)
{
T temp = t[0];
t[0] = t[i];
t[i] = temp;
Max_Heapify(t, 0, i - 1);
}
}
}
catch (std::out_of_range e)
{
std::cout << "out_of_range error" << std::endl;
}
}

void QuickSort(std::vector<T>& t)
{
_QuickSort(t, 0, t.size() - 1);
}

void CountingSort(std::vector<T>&t)
{
if (typeid(T) == typeid(int))
{
int length = t.size();
int count = 0;
T* negetiveArray;
T* positiveArray;
//前一版本将比较的次数缩减到了3(n-2)/2次,但是行数太多
for (int i = 0; i < length; i++)
{
if (t[i] < 0)
{
count++;
}
}
negetiveArray = new T[count];
positiveArray = new T[length - count];
//split the array into the postive and negetive value arraies
for (int i = 0, m = 0, n = 0; i < length; i++)
{
if (t[i] < 0)
{
negetiveArray[m] = t[i];
m++;
}
else
{
positiveArray
= t[i];
n++;
}
}
T poMin = positiveArray[0], poMax = positiveArray[0];
T neMin = negetiveArray[0], neMax = negetiveArray[0];
for (int i = 0; i < count; i++)
{
if (negetiveArray[i] < neMin)
{
neMin = negetiveArray[i];
}
if (negetiveArray[i] > neMax)
{
neMax = negetiveArray[i];
}
}
for (int i = 0; i < length - count; i++)
{
if (positiveArray[i] < poMin)
{
poMin = positiveArray[i];
}
if (positiveArray[i] > poMax)
{
poMax = positiveArray[i];
}
}
//得到正负两个数组各自的最小最大差 并将两个数组映射到0-poMin;
T poMinux = poMax - poMin;
T neMinux = neMax - neMin;

T* positiveArrayed = new T[length - count];
int* countArray = new int[poMinux + 1];
memset(countArray, 0, (poMinux + 1)*sizeof(T));

for (int i = 0; i < length - count; i++)
{
countArray[positiveArray[i] - poMin] ++;
//std::cout << countArray[i] << " ";
}
//此处与算法描述中不同的地方在于,countArray用于保存每个数存在的位置,但是该位置应该是从0开始的
for (int i = 1; i <= poMinux; i++)
{
//std::cout << countArray[i - 1] << " ";
countArray[i] = countArray[i] + countArray[i - 1];
countArray[i - 1]--;
}
countArray[poMinux]--;
//将正数数组从后往前每一个数放到应该放的地方,之所以是从后往前是为了保持算法的稳定性
for (int i = length - count - 1; i >= 0; i--)
{
positiveArrayed[countArray[positiveArray[i] - poMin]] = positiveArray[i];
countArray[positiveArray[i] - poMin]--;
}

//负值数组开始的地方
T* negetiveArrayed = new T[count];
int* countArrayNe = new int[neMinux + 1];
memset(countArrayNe, 0, (neMinux + 1)*sizeof(T));

for (int i = 0; i < count; i++)
{
countArrayNe[negetiveArray[i] - neMin]++;
}
for (int i = 1; i <= neMinux; i++)
{
countArrayNe[i] += countArrayNe[i - 1];
countArrayNe[i - 1]--;
}
countArrayNe[neMinux]--;

for (int i = count - 1; i >= 0; i--)
{
negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i];
countArrayNe[negetiveArray[i] - neMin]--;
}

//正负两个数组合并
for (int i = 0, j = 0; i < length; i++)
{
if (i < count)
{
t[i] = negetiveArrayed[i];
}
else
{
t[i] = positiveArrayed[j];
j++;
}
}

delete[] negetiveArray;
delete[] positiveArray;
delete[] countArray;
delete[] countArrayNe;
delete[] negetiveArrayed;
delete[] positiveArrayed;
}
else
{
std::cout << "you are using non-vector<int> type";
}
}

void RadixSort(std::vector<T>& t)
{
std::vector<T> positiveArray;
std::vector<T> negetiveArray;

for (iterator it = t.begin(); it != t.end(); it++)
{
if (*it < 0)
{
negetiveArray.push_back(-*it);
}
else
{
positiveArray.push_back(*it);
}
}
_RadixSort(positiveArray);
_RadixSort(negetiveArray);
int i = 0;
iterator itNe;
if (negetiveArray.size() == 0)
{
itNe = negetiveArray.end();
}
else
{
itNe = --negetiveArray.end();
}
for (iterator it = t.begin(), itPo = positiveArray.begin(); it != t.end(); it++)
{
if (i < negetiveArray.size())
{
*it = -*itNe;
i++;
if (itNe != negetiveArray.begin())
{
itNe--;
}
}
else
{
*it = *itPo;
itPo++;
}
}
}

void BucketSort(std::vector<T>& t)
{
int length = t.size();
T max = t[0], min = t[0];
for (int i = 0; i < length; i++)
{
if (t[i]>max)
{
max = t[i];
}
if (t[i] < min)
{
min = t[i];
}
}
int minux = max - min + 1;
std::vector<T>* colArray = new std::vector<T>[length];
for (iterator it = t.begin(); it != t.end(); it++)
{
int index = (*it - min)*length / minux;
colArray[index].push_back(*it);
}
for (int i = 0; i < length; i++)
{
Sort<std::vector<T>>::InsertSort(colArray[i]);
}
for (int i = 0; i < length; i++)
{
for (iterator it = colArray[i].begin(); it != colArray[i].end(); it++)
{
t[i] = *it;
}
}
delete[] colArray;
}

private:
void _MergeSort(std::vector<T>& t, int a, int b)
{
if (a<b)
{
int c = (a + b) / 2;
_MergeSort(t, a, c);
_MergeSort(t, c + 1, b);
Merge(t, a, c, b);
}
}

void Merge(std::vector<T>& t, int a, int c, int b)
{
//actually the operator[] is also using the iterator! which one is more effective?
int n1 = c - a + 1;
int n2 = b - c;
//here to create the array dynamicly, remember to delete it;
T* temp1 = new T[n1 + 1];
T* temp2 = new T[n2 + 1];

for (int i = 0; i<n1; i++)
{
temp1[i] = t[a + i];
}
//the biggest value of positive int
temp1[n1] = 2147483647;
for (int i = 0; i<n2; i++)
{
temp2[i] = t[c + 1 + i];
}
temp2[n2] = 2147483647;

int m = 0, n = 0;
for (int i = a; i <= b; i++)
{
if (temp1[m] <= temp2
)
{
t[i] = temp1[m];
m++;
}
else if (temp1[m]>temp2
)
{
t[i] = temp2
;
n++;
}
else
{

}
}
//remember to clean it
delete[] temp1;
delete[] temp2;
}

int GetLeftChild(int i)
{
return (i + 1) << 1 - 1;
}

int GetRightChild(int i)
{
return (i + 1) << 1;
}

void Max_Heapify(std::vector<T>& t, int i, int length)
{
int  largest = 0;
int l = GetLeftChild(i);
int r = GetRightChild(i);

if (l<=length && t[l]>t[i])
{
largest = l;
}
else
{
largest = i;
}

if (r<=length && t[r]>t[largest])
{
largest = r;
}

if (largest != i)
{
T temp = t[i];
t[i] = t[largest];
t[largest] = temp;
Max_Heapify(t, largest, length);
}
}

void BuildHeap(std::vector<T>& t, int length)
{
for (int i = length; i >= 0; i--)
{
Max_Heapify(t, i, length);
}
}

void _QuickSort(std::vector<T>& t, int a, int b)
{
if (a < b)
{
int s = Partition(t, a, b);
_QuickSort(t, a, s-1);
_QuickSort(t, s + 1, b);
}
}

int Partition(std::vector<T>& t, int a, int b)
{
T split = t[a];
while (a < b)
{
while (t[b] >= split && a < b)
{
b--;
}
T temp = t[a];
t[a] = t[b];
t[b] = temp;

while (t[a] <= split && a < b)
{
a++;
}
temp = t[a];
t[a] = t[b];
t[b] = temp;
}
return a;
}

inline int GetNIndex(int t, int i)
{
return (t % (int)pow(10, i + 1) - t % (int)pow(10, i)) / pow(10, i);
}

void _RadixSort(std::vector<T>& t)
{
//对于多位数来说是count位数, 而对于扑克牌问题来说就是面值和花色了
T max = t[0];
int length = t.size();
for (int i = 0; i < length; i++)
{
if (max < t[i])
{
max = t[i];
}
}
int count = 0;
//get the radix of max value;
int k = max / pow(10, count);
while (k != 0)
{
count++;
k = max / pow(10, count);
}
//int* array = new int[length*(count-1)];
//memset(array, 0, length*(count - 1)*sizeof(int));

int* positionArray = new int[length];
T* tempArray = new T[length];
//*************************************************
//change the codes more general for the problem of multi-decision sort
for (int i = 0; i < count; i++)
{
int* countArray = new int[10];
memset(countArray, 0, 10 * sizeof(10));

for (int j = 0; j < length; j++)
{
positionArray[j] = GetNIndex(t[j], i);
}
//the t is changing with positionArray;
for (int m = 0; m < length; m++)
{
countArray[positionArray[m]]++;
}
for (int m = 1; m < 10; m++)
{
countArray[m] += countArray[m - 1];
countArray[m - 1]--;
}
countArray[9]--;

for (int m = length - 1; m >= 0; m--)
{
//无论其他怎么改变 位置都是相对的 positionArray[m]就是t[m]
tempArray[countArray[positionArray[m]]] = t[m];
countArray[positionArray[m]]--;
}
for (int m = 0; m < length; m++)
{
t[m] = tempArray[m];
}
delete[] countArray;
}

delete[] positionArray;
delete[] tempArray;
}

};
#pragma endregion

#pragma region std::list<T>
template<typename T>
class Sort<std::list<T>>
{
//for the list, we can't directly use the operator+/-,because it is the list
//actually we can use the operator[] to change it, does list solved the problem?
//not effective at all
//we should support a method to increase or decrease the pointer(iterator)!
typedef typename std::list<T>::iterator iterator;

public:
void InsertSort(std::list<T>& t)
{
for (std::list<T>::iterator it = t.begin(); it != t.end(); it++)
{
std::list<T>::iterator itFront = it;
if (++it == t.end())
{
break;
}
T temp = *it;
it--;

while (*itFront > temp)
{
std::list<T>::iterator itTemp = itFront;
itTemp++;
*itTemp = *itFront;
if (itFront != t.begin())
{
itFront--;
if (itFront == t.begin() && *itFront < temp)
{
itFront++;
break;
}
}
else
{
break;
}
}
*itFront = temp;
}
}

void MergeSort(std::list<T>& t)
{
int length = t.size();
_MergeSort(t, 0, length - 1);
}

void HeapSort(std::list<T>& t)
{
//the worst palce is to find the son of iterator, it will cost too much;
int length = t.size() - 1;
BuildHeap(t);
iterator begin = t.begin();
iterator end = t.end();
end--;
for (int i = length; i >= 1; i--)
{
T temp = *end;
*end = *begin;
*begin = temp;
MaxHeapify(t, begin, i - 1);
end--;
}

}

void QuickSort(std::list<T>& t)
{
_QuickSort(t, 0, t.size() - 1);
}

void CountingSort(std::list<T>& t)
{
//偷天换日一回,将iterator操作变换成数组操作
if (typeid(T) == typeid(int))
{
int length = t.size();
int count = 0;
T* positiveArray;
T* negetiveArray;

iterator it;
for (it = t.begin(); it != t.end(); it++)
{
if (*it < 0)
{
count++;
}
}
positiveArray = new T[length-count];
negetiveArray = new T[count];
int m = 0, n = 0;
for (it = t.begin(); it != t.end(); it++)
{
if (*it < 0)
{
negetiveArray[m] = *it;
m++;
}
else
{
positiveArray
= *it;
n++;
}
}

T poMin = positiveArray[0], poMax = positiveArray[0];
T neMin = negetiveArray[0], neMax = negetiveArray[0];

for (int i = 0; i < length - count; i++)
{
if (positiveArray[i]>poMax)
{
poMax = positiveArray[i];
}
if (positiveArray[i] < poMin)
{
poMin = positiveArray[i];
}
}
for (int i = 0; i <count; i++)
{
if (negetiveArray[i]>neMax)
{
neMax = negetiveArray[i];
}
if (negetiveArray[i] < neMin)
{
neMin = negetiveArray[i];
}
}
T poMinux = poMax - poMin;
T neMinux = neMax - neMin;

//positive array
T* positiveArrayed = new T[length - count];
T* countArrayPo = new T[poMinux + 1];
memset(countArrayPo, 0, (poMinux + 1)*sizeof(T));

for (int i = 0; i < length - count; i++)
{
countArrayPo[positiveArray[i]-poMin]++;
}
for (int i = 1; i <= poMinux; i++)
{
countArrayPo[i] += countArrayPo[i - 1];
countArrayPo[i - 1]--;
}
countArrayPo[poMinux]--;
for (int i = length - count - 1; i >= 0; i--)
{
positiveArrayed[countArrayPo[positiveArray[i] - poMin]] = positiveArray[i];
countArrayPo[positiveArray[i] - poMin]--;
}
//negetive value
T* negetiveArrayed = new T[count];
T* countArrayNe = new T[neMinux + 1];
memset(countArrayNe, 0, (neMinux + 1)*sizeof(T));
for (int i = 0; i < count; i++)
{
countArrayNe[negetiveArray[i] - neMin]++;
}
for (int i = 1; i <= neMinux; i++)
{
countArrayNe[i] += countArrayNe[i - 1];
countArrayNe[i]--;
}
countArrayNe[neMinux]--;
for (int i = count - 1; i >= 0; i--)
{
negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i];
countArrayNe[negetiveArray[i] - neMin]--;
}
//gather two arraies
m = 0, n = 0;
for (it = t.begin(); it != t.end(); it++)
{
if (m < count)
{
*it = negetiveArrayed[m];
m++;
}
else
{
*it = positiveArrayed
;
n++;
}

}

delete[] positiveArray;
delete[] negetiveArray;
delete[] countArrayPo;
delete[] countArrayNe;
delete[] positiveArrayed;
delete[] negetiveArrayed;
}
else
{
std::cout << "you are using non-list<int> type\n";
}
}

void RadixSort(std::list<T>& t)
{
std::list<T> positiveArray;
std::list<T> negetiveArray;

for (iterator it = t.begin(); it != t.end(); it++)
{
if (*it < 0)
{
negetiveArray.push_back(-*it);
}
else
{
positiveArray.push_back(*it);
}
}
_RadixSort(positiveArray);
_RadixSort(negetiveArray);
int i = 0;
iterator itNe;
if (negetiveArray.size() == 0)
{
itNe = negetiveArray.end();
}
else
{
itNe = --negetiveArray.end();
}
for (iterator it = t.begin(), itPo = positiveArray.begin(); it != t.end(); it++)
{
if (i < negetiveArray.size())
{
*it = -*itNe;
i++;
if (itNe != negetiveArray.begin())
{
itNe--;
}
}
else
{
*it = *itPo;
itPo++;
}
}
}

void BucketSort(std::list<T>& t)
{
int length = t.size();
T max = *(t.begin()), min = *(t.begin());
for (iterator it = t.begin(); it != t.end(); it++)
{
if (*it > max)
{
max = *it;
}
if (*it < min)
{
min = *it;
}
}
int minux = max - min+1;
std::vector<T>* colArray = new std::vector<T>[length];
for (iterator it = t.begin(); it != t.end(); it++)
{
int index = (*it - min)*length / minux;
colArray[index].push_back(*it);
}
for (int i = 0; i < length; i++)
{
Sort<std::vector<T>> s;
s.InsertSort(colArray[i]);
}
int m = 0;
//the border condition annoys me a lot!
for (iterator it = t.begin(); it != t.end(); m++)
{
for (std::vector<T>::iterator itCol = colArray[m].begin(); itCol != colArray[m].end(); itCol++)
{
*it = *itCol;
it++;
}
}
}

private:
void _MergeSort(std::list<T>& t, int a, int b)
{
if (a<b)
{
int c = (a + b) / 2;
_MergeSort(t, a, c);
_MergeSort(t, c + 1, b);

std::list<T>::iterator ita = t.begin();
std::list<T>::iterator itc = t.begin();
std::list<T>::iterator itb = t.begin();
for (int i = 0; i <= b; i++)
{
if (i<a)
{
ita++;
}
if (i<c)
{
itc++;
}
if (i<b)
{
itb++;
}
}
Merge(t, ita, itc, itb);
}

}

//Here we can't directly use the std::list<T>::iterator, use the typedef to replace it
//compiler of ms
void  Merge(std::list<T>& t, iterator a, iterator c, iterator b)
{
std::list<T> temp1;
std::list<T>::iterator nothing = ++c;
c--;
for (std::list<T>::iterator it = a; it != nothing; it++)
{
temp1.push_back(*it);
}
temp1.push_back(2147483647);
std::list<T> temp2;
std::list<T>::iterator something = ++b;
b--;
for (std::list<T>::iterator it = nothing; it != something; it++)
{
temp2.push_back(*it);
}
temp2.push_back(2147483647);

std::list<T>::iterator itTemp1 = temp1.begin();
std::list<T>::iterator itTemp2 = temp2.begin();
for (std::list<T>::iterator it = a; it != something; it++)
{
if (*itTemp1 > *itTemp2)
{
*it = *itTemp2;
itTemp2++;
}
else
{
*it = *itTemp1;
itTemp1++;
}
}
}

iterator IteratorIncrease(std::list<T>& t, iterator it,int i)
{
iterator tempIt = it;
for (int index = 0; index < i; index++)
{
if (tempIt == t.end()--)
{
return t.end();
}
tempIt++;
}
return tempIt;
}

iterator IteratorDecrese(std::list<T>& t, iterator it, int i)
{
iterator tempIt = it;
for (int index = 0; index < i; i++)
{
if (tempIt == t.begin())
{
std::cout << "out of range with iterator in decrese";
return t.end();
}
else
{
tempIt--;
}
}
return tempIt;
}

int GetIteratorPosition(std::list<T>& t, iterator it)
{
int position = -1;
iterator tempIt = t.begin();
for (tempIt; tempIt != t.end(); tempIt++)
{
position++;
if (tempIt == it)
{
break;
}
}
if (position >= t.size())
{
return -1;
}
return position;
}

int GetLeftChild(std::list<T>& t, iterator it)
{
int number = -1;
iterator tempIt;
for (tempIt = t.begin(); tempIt != t.end(); tempIt++)
{
number++;
if (tempIt == it)
{
break;
}
}
if (number >= t.size())
{
//the it is not one of the t'iterator;
return NULL;
}

int leftChild = ((number + 1) << 1) - 1;
return leftChild;
}

int GetRightChild(std::list<T>& t, iterator it)
{
int number = -1;
iterator tempIt;
for (tempIt = t.begin(); tempIt != t.end(); tempIt++)
{
number++;
if (tempIt == it)
{
break;
}
}
if (number >= t.size())
{
//the it is not one of the t'iterator;
return NULL;
}

int RightChild = (number + 1) << 1;
return RightChild;
}

void MaxHeapify(std::list<T>& t, iterator it, int length)
{
//iterator tempIt = IteratorIncrease(t, t.begin(), length);
int leftChild = GetLeftChild(t, it);
int rightChild = GetRightChild(t, it);
int i = GetIteratorPosition(t, it);

iterator itLeft = IteratorIncrease(t, t.begin(), leftChild);
iterator itRight = IteratorIncrease(t, t.begin(), rightChild);

int largest = 0;
T tLargest;
if (leftChild <= length && *itLeft > *it)
{
largest = leftChild;
tLargest = *itLeft;
}
else
{
largest = i;
tLargest = *it;
}

if (rightChild <= length  && *itRight > tLargest)
{
largest = rightChild;
tLargest = *itRight;
}

if (largest != i)
{
T temp = *it;
*it = tLargest;

if (largest == leftChild)
{
*itLeft = temp;
MaxHeapify(t, itLeft, length);
}
else
{
*itRight = temp;
MaxHeapify(t, itRight, length);
}
}
}

void BuildHeap(std::list<T>& t)
{
for (int i = (t.size() - 1) / 2; i >= 0; i--)
{
iterator temp = IteratorIncrease(t, t.begin(), i);
MaxHeapify(t, temp, t.size()-1);
}
}

void _QuickSort(std::list<T>& t, int a, int b)
{
if (a < b)
{
int s = Partition(t, a, b);
_QuickSort(t, a, s - 1);
_QuickSort(t, s + 1, b);
}
}

int Partition(std::list<T>& t, int a, int b)
{
iterator l = IteratorIncrease(t, t.begin(), a);
iterator r = IteratorIncrease(t, t.begin(), b);

T split = *l;
while (a < b && l != t.end() && r != t.end())
{
while (a<b && *r>split)
{
b--;
r--;
}
T temp = *r;
*r = *l;
*l = temp;

while (a<b && *l < split)
{
a++;
l++;
}
temp = *l;
*l = *r;
*r = temp;
}
return a;
}

inline int GetNIndex(int t, int i)
{
return (t % (int)pow(10, i + 1) - t % (int)pow(10, i)) / pow(10, i);
}

void _RadixSort(std::list<T>& t)
{
int length = t.size();
if (length == 0)
{
return;
}
T max = *t.begin();
int count = 0;
for (iterator it = t.begin(); it != t.end(); it++)
{
if (*it > max)
{
max = *it;
}
}
int k = max / pow(10, count);
while (k != 0)
{
count++;
k = max / pow(10, count);
}

T* tempArray = new int[length];
for (int i = 0; i < count; i++)
{
int* positionArray = new int[length];
int* countArray = new int[10];
memset(countArray, 0, 10 * sizeof(int));

iterator it = t.begin();
for (int j = 0; j < length; j++)
{
positionArray[j] = GetNIndex(*it, i);
it++;
}

for (int m = 0; m < length; m++)
{
countArray[positionArray[m]]++;
}
for (int m = 1; m < 10; m++)
{
countArray[m] += countArray[m - 1];
countArray[m - 1]--;
}
countArray[9]--;
//
it = --t.end();
for (int m = length - 1; m >= 0; m--)
{
tempArray[countArray[positionArray[m]]] = *it;
countArray[positionArray[m]]--;
if (it != t.begin())
{
it--;
}
}
int m = 0;
for (it = t.begin(); it != t.end(); it++)
{
*it = tempArray[m];
m++;
}
delete[] positionArray;
delete[] countArray;
}
delete[] tempArray;
}
};

#pragma endregion


  过段时间再贴上树这种树(非二叉树)结构的模板,其格式也会向标准模板靠齐,基本功能已经具有,但是还不够强大,远没有达到通用的标准。其存储结构是孩子兄弟存储法,针对树的前序遍历已经写好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: