模板化的七种排序算法,适用于T* vector<T>以及list<T>
最近在写一些数据结构以及算法相关的代码,比如常用排序算法以及具有启发能力的智能算法。为了能够让写下的代码下次还能够被复用,直接将代码编写成类模板成员函数的方式,之所以没有将这种方式改成更方便的函数模板纯属于偷懒,更方便于测试代码的有效性,等代码写完也懒得去改了。下面开始介绍这段代码,有什么不对的地方欢迎前来指正。
一共写了七种排序,插入排序InsertSort、堆排序HeapSort、快速排序QuickSort、合并排序MergeSort,计数排序CountingSort,基数排序RadixSort,桶排序BucketSort。排序思想都是根据<<Introduction to Algorithms>>而来的,所以对于这本书里面的时间复杂度都是严格遵从的,本文就不详细介绍这些算法的思想和实现机制了。针对于这七种排序,先写一个非特化的模板类Sort空着,是为了能够让模板的特化正确通过编译,接着写三个特化版本的Sort类,三个特化的版本分别接受T* vector<T>以及list<T>作为模板形参,而其中的各个成员函数接受的参数也是这些类型。函数体没有写的情况大致如下:
1 template<typename T> 2 class Sort 3 { 4 5 }; 6 7 template<typename T> 8 class Sort<T*> 9 { 10 public: 11 void InsertSort(T* t, int length = 0) 12 { 13 } 14 15 //the hardest part is to judge the correctness 16 void MergeSort(T* t, int length = 0) 17 { 18 } 19 20 void HeapSort(T* t, int length = 0) 21 { 22 } 23 24 void QuickSort(T* t, int length = 0) 25 { 26 } 27 28 void CountingSort(T* t, int length = 0) 29 { 30 } 31 32 void RadixSort(T* t, int length = 0) 33 { 34 } 35 36 void BucketSort(T* t, int length = 0) 37 { 38 } 39 40 template<typename T> 41 class Sort<std::vector<T>> 42 { 43 public: 44 void InsertSort(std::vector<T>& t) 45 { 46 } 47 48 void HeapSort(std::vector<T>& t) 49 { 50 } 51 52 void QuickSort(std::vector<T>& t) 53 { 54 } 55 56 void CountingSort(std::vector<T>&t) 57 { 58 } 59 60 void RadixSort(std::vector<T>& t) 61 { 62 } 63 64 void BucketSort(std::vector<T>& t) 65 { 66 } 67 }; 68 69 template<typename T> 70 class Sort<std::list<T>> 71 { 72 public: 73 void InsertSort(std::list<T>& t) 74 { 75 } 76 77 void MergeSort(std::list<T>& t) 78 { 79 } 80 81 void HeapSort(std::list<T>& t) 82 { 83 } 84 85 void QuickSort(std::list<T>& t) 86 { 87 } 88 89 void CountingSort(std::list<T>& t) 90 { 91 } 92 93 void RadixSort(std::list<T>& t) 94 { 95 } 96 97 void BucketSort(std::list<T>& t) 98 { 99 } 100 101 };
对于编译期决定的类型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算法的三种如下所示:
1 #include <vector> 2 #include <iostream> 3 #include <list> 4 #include <exception> 5 #include <iterator> 6 #include <math.h> 7 8 template<typename T> 9 class Sort 10 { 11 12 }; 13 14 template<typename T> 15 class Sort<T*> 16 { 17 public: 18 void InsertSort(T* t, int length = 0) 19 { 20 if (t == NULL) 21 { 22 std::cout << "are you fucking kidding me?"; 23 } 24 else 25 { 26 //<<introduction to algorithm>> the array is from 1, we are from 0 27 for (int i = 1; i<length; i++) 28 { 29 T temp = t[i]; 30 int j = i - 1; 31 while (j >= 0 && t[j]>temp) 32 { 33 t[j + 1] = t[j]; 34 --j; 35 } 36 t[j + 1] = temp; 37 } 38 } 39 } 40 }; 41 42 #pragma region std::vector<T> 43 template<typename T> 44 class Sort<std::vector<T>> 45 { 46 public: 47 typedef typename std::vector<T>::iterator iterator; 48 public: 49 //actually vector use the operator[] should be faster 50 //the operator[] also used iterator 51 void InsertSort(std::vector<T>& t) 52 { 53 if (t.size()>0) 54 { 55 for (std::vector<T>::iterator it = t.begin() + 1; it != t.end(); it++) 56 { 57 std::vector<T>::iterator itFront = it - 1; 58 T temp = *(it); 59 60 while (*itFront > temp) 61 { 62 std::vector<T>::iterator itTemp = itFront; 63 itTemp++; 64 *itTemp = *itFront; 65 if (itFront != t.begin()) 66 { 67 itFront--; 68 if (itFront == t.begin() && *itFront < temp) 69 { 70 itFront++; 71 break; 72 } 73 } 74 else 75 { 76 break; 77 } 78 } 79 *(itFront) = temp; 80 } 81 } 82 } 83 }; 84 #pragma endregion 85 86 #pragma region std::list<T> 87 template<typename T> 88 class Sort<std::list<T>> 89 { 90 //for the list, we can't directly use the operator+/-,because it is the list 91 //actually we can use the operator[] to change it, does list solved the problem? 92 //not effective at all 93 //we should support a method to increase or decrease the pointer(iterator)! 94 typedef typename std::list<T>::iterator iterator; 95 96 public: 97 void InsertSort(std::list<T>& t) 98 { 99 for (std::list<T>::iterator it = t.begin(); it != t.end(); it++) 100 { 101 std::list<T>::iterator itFront = it; 102 if (++it == t.end()) 103 { 104 break; 105 } 106 T temp = *it; 107 it--; 108 109 while (*itFront > temp) 110 { 111 std::list<T>::iterator itTemp = itFront; 112 itTemp++; 113 *itTemp = *itFront; 114 if (itFront != t.begin()) 115 { 116 itFront--; 117 if (itFront == t.begin() && *itFront < temp) 118 { 119 itFront++; 120 break; 121 } 122 } 123 else 124 { 125 break; 126 } 127 } 128 *itFront = temp; 129 } 130 } 131 132 }; 133 134 #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/,这个就比较麻烦了,估计很少有这个需求的用户类。
下面则是全部的代码:
1 #include <vector> 2 #include <iostream> 3 #include <list> 4 #include <exception> 5 #include <iterator> 6 #include <math.h> 7 8 template<typename T> 9 class Sort 10 { 11 12 }; 13 14 template<typename T> 15 class Sort<T*> 16 { 17 public: 18 void InsertSort(T* t, int length = 0) 19 { 20 if (t == NULL) 21 { 22 std::cout << "are you fucking kidding me?"; 23 } 24 else 25 { 26 //<<introduction to algorithm>> the array is from 1, we are from 0 27 for (int i = 1; i<length; i++) 28 { 29 T temp = t[i]; 30 int j = i - 1; 31 while (j >= 0 && t[j]>temp) 32 { 33 t[j + 1] = t[j]; 34 --j; 35 } 36 t[j + 1] = temp; 37 } 38 } 39 } 40 41 //the hardest part is to judge the correctness 42 void MergeSort(T* t, int length = 0) 43 { 44 _MergeSort(t, 0, length - 1); 45 } 46 47 void HeapSort(T* t, int length = 0) 48 { 49 try 50 { 51 if (length>0) 52 { 53 length = length - 1; 54 BuildHeap(t, length); 55 for (int i = length; i >= 0; i--) 56 { 57 T temp = t[0]; 58 t[0] = t[i]; 59 t[i] = temp; 60 Max_Heapify(t, 0, i - 1); 61 } 62 } 63 } 64 catch (std::out_of_range e) 65 { 66 std::cout << "out_of_range error" << std::endl; 67 } 68 } 69 70 void QuickSort(T* t, int length = 0) 71 { 72 _QuickSort(t, 0, length-1); 73 } 74 75 //this one can only work in integer, negetive value is also included 76 void CountingSort(T* t, int length = 0) 77 { 78 if (typeid(T) == typeid(int)) 79 { 80 //one iterator to check the min, max, the number of negetive value 81 int count = 0; 82 T* negetiveArray; 83 T* positiveArray; 84 //前一版本将比较的次数缩减到了3(n-2)/2次,但是行数太多 85 for (int i = 0; i < length; i++) 86 { 87 if (t[i] < 0) 88 { 89 count++; 90 } 91 } 92 negetiveArray = new T[count]; 93 positiveArray = new T[length - count]; 94 //split the array into the postive and negetive value arrays 95 for (int i = 0, m = 0, n = 0; i < length; i++) 96 { 97 if (t[i] < 0) 98 { 99 negetiveArray[m] = t[i]; 100 m++; 101 } 102 else 103 { 104 positiveArray[n] = t[i]; 105 n++; 106 } 107 } 108 T poMin = positiveArray[0], poMax = positiveArray[0]; 109 T neMin = negetiveArray[0], neMax = negetiveArray[0]; 110 for (int i = 0; i < count; i++) 111 { 112 if (negetiveArray[i] < neMin) 113 { 114 neMin = negetiveArray[i]; 115 } 116 if (negetiveArray[i] > neMax) 117 { 118 neMax = negetiveArray[i]; 119 } 120 } 121 for (int i = 0; i < length - count; i++) 122 { 123 if (positiveArray[i] < poMin) 124 { 125 poMin = positiveArray[i]; 126 } 127 if (positiveArray[i] > poMax) 128 { 129 poMax = positiveArray[i]; 130 } 131 } 132 //得到正负两个数组各自的最小最大差 并将两个数组映射到0-poMin; 133 T poMinux = poMax - poMin; 134 T neMinux = neMax - neMin; 135 136 T* positiveArrayed = new T[length - count]; 137 int* countArray = new int[poMinux + 1]; 138 memset(countArray, 0, (poMinux + 1)*sizeof(T)); 139 140 for (int i = 0; i < length - count; i++) 141 { 142 countArray[positiveArray[i] - poMin] ++; 143 //std::cout << countArray[i] << " "; 144 } 145 //此处与算法描述中不同的地方在于,countArray用于保存每个数存在的位置,但是该位置应该是从0开始的 146 for (int i = 1; i <= poMinux; i++) 147 { 148 //std::cout << countArray[i - 1] << " "; 149 countArray[i] = countArray[i] + countArray[i - 1]; 150 countArray[i - 1]--; 151 } 152 countArray[poMinux]--; 153 //将正数数组从后往前每一个数放到应该放的地方,之所以是从后往前是为了保持算法的稳定性 154 for (int i = length - count - 1; i >= 0; i--) 155 { 156 positiveArrayed[countArray[positiveArray[i] - poMin]] = positiveArray[i]; 157 countArray[positiveArray[i] - poMin]--; 158 } 159 160 //负值数组开始的地方 161 T* negetiveArrayed = new T[count]; 162 int* countArrayNe = new int[neMinux + 1]; 163 memset(countArrayNe, 0, (neMinux + 1)*sizeof(T)); 164 165 for (int i = 0; i < count; i++) 166 { 167 countArrayNe[negetiveArray[i] - neMin]++; 168 } 169 for (int i = 1; i <= neMinux; i++) 170 { 171 countArrayNe[i] += countArrayNe[i - 1]; 172 countArrayNe[i - 1]--; 173 } 174 countArrayNe[neMinux]--; 175 176 for (int i = count - 1; i >= 0; i--) 177 { 178 negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i]; 179 countArrayNe[negetiveArray[i] - neMin]--; 180 } 181 182 //正负两个数组合并 183 for (int i = 0, j = 0; i < length; i++) 184 { 185 if (i < count) 186 { 187 t[i] = negetiveArrayed[i]; 188 } 189 else 190 { 191 t[i] = positiveArrayed[j]; 192 j++; 193 } 194 } 195 196 delete[] negetiveArray; 197 delete[] positiveArray; 198 delete[] countArray; 199 delete[] countArrayNe; 200 delete[] negetiveArrayed; 201 delete[] positiveArrayed; 202 } 203 else 204 { 205 std::cout << "you are using non-int type array for Counting Sort" << std::endl; 206 } 207 } 208 209 void RadixSort(T* t, int length = 0) 210 { 211 int count = 0; 212 for (int i = 0; i < length; i++) 213 { 214 if (t[i] < 0) 215 { 216 count++; 217 } 218 } 219 T* positiveArray = new T[length - count]; 220 T* negetiveArray = new T[count]; 221 222 for (int i = 0, m=0, n=0; i < length; i++) 223 { 224 if (t[i] < 0) 225 { 226 negetiveArray[m] = -t[i]; 227 m++; 228 } 229 else 230 { 231 positiveArray[n] = t[i]; 232 n++; 233 } 234 } 235 _RadixSort(positiveArray, length - count); 236 _RadixSort(negetiveArray, count); 237 for (int i = 0, m=count-1, n =0; i < length; i++) 238 { 239 if (i < count) 240 { 241 t[i] = -negetiveArray[m]; 242 m--; 243 } 244 else 245 { 246 t[i] = positiveArray[n]; 247 n++; 248 } 249 } 250 } 251 252 void BucketSort(T* t, int length = 0) 253 { 254 /* 255 this one does't like other linear time sorting, the basic type are all received for the parameter 256 and the class which supports operator[], operator - and operator > (< == ...). 257 */ 258 //if we achieve the algrithm with T*, it will need more time and space to judge the length of array's array 259 //struct, vector, list are all useful. this one is using the data structrue to decrease time; 260 261 /* 262 The first version is using struct to construct the bucket, then i found that i did't finish the sort for the 263 linked list (sort by the pointer of a linked list) 264 */ 265 266 T max = t[0], min = t[0]; 267 for (int i = 0; i < length; i++) 268 { 269 if (t[i]>max) 270 { 271 max = t[i]; 272 } 273 if (t[i] < min) 274 { 275 min = t[i]; 276 } 277 } 278 int minux = max - min +1; 279 //std::vector<std::vector<T>> colArray; 280 std::vector<T>* colArray = new std::vector<T>[length]; 281 //std::vector<T> rawArray; 282 for (int i = 0; i < length; i++) 283 { 284 int index = (t[i] - min)*length / minux; 285 std::vector<T> & rawArray = colArray[index]; 286 rawArray.push_back(t[i]); 287 } 288 for (int i = 0; i < length; i++) 289 { 290 std::vector<T>& rawArray = colArray[i]; 291 Sort<std::vector<T>>::InsertSort(rawArray); 292 } 293 for (int i = 0, index=0; i < length; i++) 294 { 295 std::vector<T> & rawArray = colArray[i]; 296 //int j = 0; 297 for (std::vector<T>::iterator it = rawArray.begin(); it != rawArray.end(); it++) 298 { 299 t[index] = *it; 300 index++; 301 } 302 } 303 delete[] colArray; 304 } 305 306 private: 307 void _MergeSort(T* t, int a, int b) 308 { 309 if (a<b) 310 { 311 int c = (a + b) / 2; 312 _MergeSort(t, a, c); 313 _MergeSort(t, c + 1, b); 314 Merge(t, a, c, b); 315 } 316 } 317 318 void Merge(T* t, int a, int c, int b) 319 { 320 int n1 = c - a + 1; 321 int n2 = b - c; 322 //here to create the array dynamicly, remember to delete it; 323 T* temp1 = new T[n1 + 1]; 324 T* temp2 = new T[n2 + 1]; 325 326 for (int i = 0; i<n1; i++) 327 { 328 temp1[i] = t[a + i]; 329 } 330 //the biggest value of positive int 331 temp1[n1] = 2147483647; 332 for (int i = 0; i<n2; i++) 333 { 334 temp2[i] = t[c + 1 + i]; 335 } 336 temp2[n2] = 2147483647; 337 338 int m = 0, n = 0; 339 for (int i = a; i <= b; i++) 340 { 341 if (temp1[m] <= temp2[n]) 342 { 343 t[i] = temp1[m]; 344 m++; 345 } 346 else if (temp1[m]>temp2[n]) 347 { 348 t[i] = temp2[n]; 349 n++; 350 } 351 } 352 //remember to clean it 353 delete[] temp1; 354 delete[] temp2; 355 } 356 357 //i-root re-heap; 358 //abstract from the tree, but did not used tree; 359 void Max_Heapify(T* t, int i, int length) 360 { 361 int largest = 0; 362 int l = GetLeftChild(i); 363 int r = GetRightChild(i); 364 365 if (l <= length && t[i] <t[l]) 366 { 367 largest = l; 368 } 369 else 370 { 371 largest = i; 372 } 373 374 if (r <= length && t[largest] < t[r]) 375 { 376 largest = r; 377 } 378 379 if (largest != i) 380 { 381 T temp = t[i]; 382 t[i] = t[largest]; 383 t[largest] = temp; 384 Max_Heapify(t, largest, length); 385 } 386 } 387 388 inline int GetLeftChild(int i) 389 { 390 return ((i + 1) << 1) - 1; 391 } 392 393 inline int GetRightChild(int i) 394 { 395 return (i + 1) << 1; 396 } 397 398 void BuildHeap(T* t, int length) 399 { 400 //after the length/2, then it should not be the tree node 401 for (int i = length / 2; i >= 0; i--) 402 { 403 Max_Heapify(t, i, length); 404 } 405 } 406 407 void _QuickSort(T* t, int a, int b) 408 { 409 if (a<b) 410 { 411 int s = Partition(t, a, b); 412 _QuickSort(t, a, s-1); 413 _QuickSort(t, s + 1, b); 414 } 415 } 416 417 int Partition(T* t, int a, int b) 418 { 419 T split = t[a]; 420 //when the a equals b, a should be the split! 421 while (a < b) 422 { 423 while (t[b] >= split && a < b) 424 { 425 b--; 426 } 427 T temp = t[a]; 428 t[a] = t[b]; 429 t[b] = temp; 430 431 while (t[a] <= split && a < b) 432 { 433 a++; 434 } 435 temp = t[a]; 436 t[a] = t[b]; 437 t[b] = temp; 438 } 439 return a; 440 } 441 442 //get the index's number of t 443 inline int GetNIndex(int t, int i) 444 { 445 return (t%(int)pow(10, i + 1) - t%(int)pow(10, i))/pow(10,i); 446 } 447 448 int* GetAllIndex(int t, int count) 449 { 450 int* array = new int[count]; 451 memset(array, 0, count*sizeof(int)); 452 int i = 0, sum = 0; 453 while (t / pow(10, i) > 0) 454 { 455 int temp = t%pow(10, i + 1) - sum; 456 sum += array[i]; 457 array[i] = temp / pow(10, i); 458 i++; 459 } 460 return array; 461 } 462 463 void _RadixSort(T* t, int length = 0) 464 { 465 //对于多位数来说是count位数, 而对于扑克牌问题来说就是面值和花色了 466 T max = t[0]; 467 for (int i = 0; i < length; i++) 468 { 469 if (max < t[i]) 470 { 471 max = t[i]; 472 } 473 } 474 int count = 0; 475 //get the radix of max value; 476 int k = max / pow(10, count); 477 while (k != 0) 478 { 479 count++; 480 k = max / pow(10, count); 481 } 482 //int* array = new int[length*(count-1)]; 483 //memset(array, 0, length*(count - 1)*sizeof(int)); 484 485 int* positionArray = new int[length]; 486 T* tempArray = new T[length]; 487 //************************************************* 488 //change the codes more general for the problem of multi-decision sort 489 //using counting sort to solve every single problem; 490 for (int i = 0; i < count; i++) 491 { 492 int* countArray = new int[10]; 493 memset(countArray, 0, 10 * sizeof(10)); 494 495 for (int j = 0; j < length; j++) 496 { 497 positionArray[j] = GetNIndex(t[j], i); 498 } 499 //the t is changing with positionArray; 500 for (int m = 0; m < length; m++) 501 { 502 countArray[positionArray[m]]++; 503 } 504 for (int m = 1; m < 10; m++) 505 { 506 countArray[m] += countArray[m - 1]; 507 countArray[m - 1]--; 508 } 509 countArray[9]--; 510 511 for (int m = length - 1; m >= 0; m--) 512 { 513 //无论其他怎么改变 位置都是相对的 positionArray[m]就是t[m] 514 tempArray[countArray[positionArray[m]]] = t[m]; 515 countArray[positionArray[m]]--; 516 } 517 for (int m = 0; m < length; m++) 518 { 519 t[m] = tempArray[m]; 520 } 521 delete[] countArray; 522 } 523 524 delete[] positionArray; 525 delete[] tempArray; 526 } 527 }; 528 529 #pragma region std::vector<T> 530 template<typename T> 531 class Sort<std::vector<T>> 532 { 533 public: 534 typedef typename std::vector<T>::iterator iterator; 535 public: 536 //actually vector use the operator[] should be faster 537 //the operator[] also used iterator 538 void InsertSort(std::vector<T>& t) 539 { 540 if (t.size()>0) 541 { 542 for (std::vector<T>::iterator it = t.begin() + 1; it != t.end(); it++) 543 { 544 std::vector<T>::iterator itFront = it - 1; 545 T temp = *(it); 546 547 while (*itFront > temp) 548 { 549 std::vector<T>::iterator itTemp = itFront; 550 itTemp++; 551 *itTemp = *itFront; 552 if (itFront != t.begin()) 553 { 554 itFront--; 555 if (itFront == t.begin() && *itFront < temp) 556 { 557 itFront++; 558 break; 559 } 560 } 561 else 562 { 563 break; 564 } 565 } 566 *(itFront) = temp; 567 } 568 } 569 } 570 571 void MergeSort(std::vector<T>& t) 572 { 573 int length = t.size(); 574 if (length <= 1) 575 { 576 return; 577 } 578 else 579 { 580 _MergeSort(t, 0, length - 1); 581 } 582 } 583 584 void HeapSort(std::vector<T>& t) 585 { 586 int length = t.size(); 587 try 588 { 589 if (length>0) 590 { 591 length = length - 1; 592 BuildHeap(t, length); 593 for (int i = length; i >= 0; i--) 594 { 595 T temp = t[0]; 596 t[0] = t[i]; 597 t[i] = temp; 598 Max_Heapify(t, 0, i - 1); 599 } 600 } 601 } 602 catch (std::out_of_range e) 603 { 604 std::cout << "out_of_range error" << std::endl; 605 } 606 } 607 608 void QuickSort(std::vector<T>& t) 609 { 610 _QuickSort(t, 0, t.size() - 1); 611 } 612 613 void CountingSort(std::vector<T>&t) 614 { 615 if (typeid(T) == typeid(int)) 616 { 617 int length = t.size(); 618 int count = 0; 619 T* negetiveArray; 620 T* positiveArray; 621 //前一版本将比较的次数缩减到了3(n-2)/2次,但是行数太多 622 for (int i = 0; i < length; i++) 623 { 624 if (t[i] < 0) 625 { 626 count++; 627 } 628 } 629 negetiveArray = new T[count]; 630 positiveArray = new T[length - count]; 631 //split the array into the postive and negetive value arraies 632 for (int i = 0, m = 0, n = 0; i < length; i++) 633 { 634 if (t[i] < 0) 635 { 636 negetiveArray[m] = t[i]; 637 m++; 638 } 639 else 640 { 641 positiveArray[n] = t[i]; 642 n++; 643 } 644 } 645 T poMin = positiveArray[0], poMax = positiveArray[0]; 646 T neMin = negetiveArray[0], neMax = negetiveArray[0]; 647 for (int i = 0; i < count; i++) 648 { 649 if (negetiveArray[i] < neMin) 650 { 651 neMin = negetiveArray[i]; 652 } 653 if (negetiveArray[i] > neMax) 654 { 655 neMax = negetiveArray[i]; 656 } 657 } 658 for (int i = 0; i < length - count; i++) 659 { 660 if (positiveArray[i] < poMin) 661 { 662 poMin = positiveArray[i]; 663 } 664 if (positiveArray[i] > poMax) 665 { 666 poMax = positiveArray[i]; 667 } 668 } 669 //得到正负两个数组各自的最小最大差 并将两个数组映射到0-poMin; 670 T poMinux = poMax - poMin; 671 T neMinux = neMax - neMin; 672 673 T* positiveArrayed = new T[length - count]; 674 int* countArray = new int[poMinux + 1]; 675 memset(countArray, 0, (poMinux + 1)*sizeof(T)); 676 677 for (int i = 0; i < length - count; i++) 678 { 679 countArray[positiveArray[i] - poMin] ++; 680 //std::cout << countArray[i] << " "; 681 } 682 //此处与算法描述中不同的地方在于,countArray用于保存每个数存在的位置,但是该位置应该是从0开始的 683 for (int i = 1; i <= poMinux; i++) 684 { 685 //std::cout << countArray[i - 1] << " "; 686 countArray[i] = countArray[i] + countArray[i - 1]; 687 countArray[i - 1]--; 688 } 689 countArray[poMinux]--; 690 //将正数数组从后往前每一个数放到应该放的地方,之所以是从后往前是为了保持算法的稳定性 691 for (int i = length - count - 1; i >= 0; i--) 692 { 693 positiveArrayed[countArray[positiveArray[i] - poMin]] = positiveArray[i]; 694 countArray[positiveArray[i] - poMin]--; 695 } 696 697 //负值数组开始的地方 698 T* negetiveArrayed = new T[count]; 699 int* countArrayNe = new int[neMinux + 1]; 700 memset(countArrayNe, 0, (neMinux + 1)*sizeof(T)); 701 702 for (int i = 0; i < count; i++) 703 { 704 countArrayNe[negetiveArray[i] - neMin]++; 705 } 706 for (int i = 1; i <= neMinux; i++) 707 { 708 countArrayNe[i] += countArrayNe[i - 1]; 709 countArrayNe[i - 1]--; 710 } 711 countArrayNe[neMinux]--; 712 713 for (int i = count - 1; i >= 0; i--) 714 { 715 negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i]; 716 countArrayNe[negetiveArray[i] - neMin]--; 717 } 718 719 //正负两个数组合并 720 for (int i = 0, j = 0; i < length; i++) 721 { 722 if (i < count) 723 { 724 t[i] = negetiveArrayed[i]; 725 } 726 else 727 { 728 t[i] = positiveArrayed[j]; 729 j++; 730 } 731 } 732 733 delete[] negetiveArray; 734 delete[] positiveArray; 735 delete[] countArray; 736 delete[] countArrayNe; 737 delete[] negetiveArrayed; 738 delete[] positiveArrayed; 739 } 740 else 741 { 742 std::cout << "you are using non-vector<int> type"; 743 } 744 } 745 746 void RadixSort(std::vector<T>& t) 747 { 748 std::vector<T> positiveArray; 749 std::vector<T> negetiveArray; 750 751 for (iterator it = t.begin(); it != t.end(); it++) 752 { 753 if (*it < 0) 754 { 755 negetiveArray.push_back(-*it); 756 } 757 else 758 { 759 positiveArray.push_back(*it); 760 } 761 } 762 _RadixSort(positiveArray); 763 _RadixSort(negetiveArray); 764 int i = 0; 765 iterator itNe; 766 if (negetiveArray.size() == 0) 767 { 768 itNe = negetiveArray.end(); 769 } 770 else 771 { 772 itNe = --negetiveArray.end(); 773 } 774 for (iterator it = t.begin(), itPo = positiveArray.begin(); it != t.end(); it++) 775 { 776 if (i < negetiveArray.size()) 777 { 778 *it = -*itNe; 779 i++; 780 if (itNe != negetiveArray.begin()) 781 { 782 itNe--; 783 } 784 } 785 else 786 { 787 *it = *itPo; 788 itPo++; 789 } 790 } 791 } 792 793 void BucketSort(std::vector<T>& t) 794 { 795 int length = t.size(); 796 T max = t[0], min = t[0]; 797 for (int i = 0; i < length; i++) 798 { 799 if (t[i]>max) 800 { 801 max = t[i]; 802 } 803 if (t[i] < min) 804 { 805 min = t[i]; 806 } 807 } 808 int minux = max - min + 1; 809 std::vector<T>* colArray = new std::vector<T>[length]; 810 for (iterator it = t.begin(); it != t.end(); it++) 811 { 812 int index = (*it - min)*length / minux; 813 colArray[index].push_back(*it); 814 } 815 for (int i = 0; i < length; i++) 816 { 817 Sort<std::vector<T>>::InsertSort(colArray[i]); 818 } 819 for (int i = 0; i < length; i++) 820 { 821 for (iterator it = colArray[i].begin(); it != colArray[i].end(); it++) 822 { 823 t[i] = *it; 824 } 825 } 826 delete[] colArray; 827 } 828 829 private: 830 void _MergeSort(std::vector<T>& t, int a, int b) 831 { 832 if (a<b) 833 { 834 int c = (a + b) / 2; 835 _MergeSort(t, a, c); 836 _MergeSort(t, c + 1, b); 837 Merge(t, a, c, b); 838 } 839 } 840 841 void Merge(std::vector<T>& t, int a, int c, int b) 842 { 843 //actually the operator[] is also using the iterator! which one is more effective? 844 int n1 = c - a + 1; 845 int n2 = b - c; 846 //here to create the array dynamicly, remember to delete it; 847 T* temp1 = new T[n1 + 1]; 848 T* temp2 = new T[n2 + 1]; 849 850 for (int i = 0; i<n1; i++) 851 { 852 temp1[i] = t[a + i]; 853 } 854 //the biggest value of positive int 855 temp1[n1] = 2147483647; 856 for (int i = 0; i<n2; i++) 857 { 858 temp2[i] = t[c + 1 + i]; 859 } 860 temp2[n2] = 2147483647; 861 862 int m = 0, n = 0; 863 for (int i = a; i <= b; i++) 864 { 865 if (temp1[m] <= temp2[n]) 866 { 867 t[i] = temp1[m]; 868 m++; 869 } 870 else if (temp1[m]>temp2[n]) 871 { 872 t[i] = temp2[n]; 873 n++; 874 } 875 else 876 { 877 878 } 879 } 880 //remember to clean it 881 delete[] temp1; 882 delete[] temp2; 883 } 884 885 int GetLeftChild(int i) 886 { 887 return (i + 1) << 1 - 1; 888 } 889 890 int GetRightChild(int i) 891 { 892 return (i + 1) << 1; 893 } 894 895 void Max_Heapify(std::vector<T>& t, int i, int length) 896 { 897 int largest = 0; 898 int l = GetLeftChild(i); 899 int r = GetRightChild(i); 900 901 if (l<=length && t[l]>t[i]) 902 { 903 largest = l; 904 } 905 else 906 { 907 largest = i; 908 } 909 910 911 if (r<=length && t[r]>t[largest]) 912 { 913 largest = r; 914 } 915 916 if (largest != i) 917 { 918 T temp = t[i]; 919 t[i] = t[largest]; 920 t[largest] = temp; 921 Max_Heapify(t, largest, length); 922 } 923 } 924 925 void BuildHeap(std::vector<T>& t, int length) 926 { 927 for (int i = length; i >= 0; i--) 928 { 929 Max_Heapify(t, i, length); 930 } 931 } 932 933 void _QuickSort(std::vector<T>& t, int a, int b) 934 { 935 if (a < b) 936 { 937 int s = Partition(t, a, b); 938 _QuickSort(t, a, s-1); 939 _QuickSort(t, s + 1, b); 940 } 941 } 942 943 int Partition(std::vector<T>& t, int a, int b) 944 { 945 T split = t[a]; 946 while (a < b) 947 { 948 while (t[b] >= split && a < b) 949 { 950 b--; 951 } 952 T temp = t[a]; 953 t[a] = t[b]; 954 t[b] = temp; 955 956 while (t[a] <= split && a < b) 957 { 958 a++; 959 } 960 temp = t[a]; 961 t[a] = t[b]; 962 t[b] = temp; 963 } 964 return a; 965 } 966 967 inline int GetNIndex(int t, int i) 968 { 969 return (t % (int)pow(10, i + 1) - t % (int)pow(10, i)) / pow(10, i); 970 } 971 972 void _RadixSort(std::vector<T>& t) 973 { 974 //对于多位数来说是count位数, 而对于扑克牌问题来说就是面值和花色了 975 T max = t[0]; 976 int length = t.size(); 977 for (int i = 0; i < length; i++) 978 { 979 if (max < t[i]) 980 { 981 max = t[i]; 982 } 983 } 984 int count = 0; 985 //get the radix of max value; 986 int k = max / pow(10, count); 987 while (k != 0) 988 { 989 count++; 990 k = max / pow(10, count); 991 } 992 //int* array = new int[length*(count-1)]; 993 //memset(array, 0, length*(count - 1)*sizeof(int)); 994 995 int* positionArray = new int[length]; 996 T* tempArray = new T[length]; 997 //************************************************* 998 //change the codes more general for the problem of multi-decision sort 999 for (int i = 0; i < count; i++) 1000 { 1001 int* countArray = new int[10]; 1002 memset(countArray, 0, 10 * sizeof(10)); 1003 1004 for (int j = 0; j < length; j++) 1005 { 1006 positionArray[j] = GetNIndex(t[j], i); 1007 } 1008 //the t is changing with positionArray; 1009 for (int m = 0; m < length; m++) 1010 { 1011 countArray[positionArray[m]]++; 1012 } 1013 for (int m = 1; m < 10; m++) 1014 { 1015 countArray[m] += countArray[m - 1]; 1016 countArray[m - 1]--; 1017 } 1018 countArray[9]--; 1019 1020 for (int m = length - 1; m >= 0; m--) 1021 { 1022 //无论其他怎么改变 位置都是相对的 positionArray[m]就是t[m] 1023 tempArray[countArray[positionArray[m]]] = t[m]; 1024 countArray[positionArray[m]]--; 1025 } 1026 for (int m = 0; m < length; m++) 1027 { 1028 t[m] = tempArray[m]; 1029 } 1030 delete[] countArray; 1031 } 1032 1033 delete[] positionArray; 1034 delete[] tempArray; 1035 } 1036 1037 }; 1038 #pragma endregion 1039 1040 #pragma region std::list<T> 1041 template<typename T> 1042 class Sort<std::list<T>> 1043 { 1044 //for the list, we can't directly use the operator+/-,because it is the list 1045 //actually we can use the operator[] to change it, does list solved the problem? 1046 //not effective at all 1047 //we should support a method to increase or decrease the pointer(iterator)! 1048 typedef typename std::list<T>::iterator iterator; 1049 1050 public: 1051 void InsertSort(std::list<T>& t) 1052 { 1053 for (std::list<T>::iterator it = t.begin(); it != t.end(); it++) 1054 { 1055 std::list<T>::iterator itFront = it; 1056 if (++it == t.end()) 1057 { 1058 break; 1059 } 1060 T temp = *it; 1061 it--; 1062 1063 while (*itFront > temp) 1064 { 1065 std::list<T>::iterator itTemp = itFront; 1066 itTemp++; 1067 *itTemp = *itFront; 1068 if (itFront != t.begin()) 1069 { 1070 itFront--; 1071 if (itFront == t.begin() && *itFront < temp) 1072 { 1073 itFront++; 1074 break; 1075 } 1076 } 1077 else 1078 { 1079 break; 1080 } 1081 } 1082 *itFront = temp; 1083 } 1084 } 1085 1086 void MergeSort(std::list<T>& t) 1087 { 1088 int length = t.size(); 1089 _MergeSort(t, 0, length - 1); 1090 } 1091 1092 void HeapSort(std::list<T>& t) 1093 { 1094 //the worst palce is to find the son of iterator, it will cost too much; 1095 int length = t.size() - 1; 1096 BuildHeap(t); 1097 iterator begin = t.begin(); 1098 iterator end = t.end(); 1099 end--; 1100 for (int i = length; i >= 1; i--) 1101 { 1102 T temp = *end; 1103 *end = *begin; 1104 *begin = temp; 1105 MaxHeapify(t, begin, i - 1); 1106 end--; 1107 } 1108 1109 } 1110 1111 void QuickSort(std::list<T>& t) 1112 { 1113 _QuickSort(t, 0, t.size() - 1); 1114 } 1115 1116 void CountingSort(std::list<T>& t) 1117 { 1118 //偷天换日一回,将iterator操作变换成数组操作 1119 if (typeid(T) == typeid(int)) 1120 { 1121 int length = t.size(); 1122 int count = 0; 1123 T* positiveArray; 1124 T* negetiveArray; 1125 1126 iterator it; 1127 for (it = t.begin(); it != t.end(); it++) 1128 { 1129 if (*it < 0) 1130 { 1131 count++; 1132 } 1133 } 1134 positiveArray = new T[length-count]; 1135 negetiveArray = new T[count]; 1136 int m = 0, n = 0; 1137 for (it = t.begin(); it != t.end(); it++) 1138 { 1139 if (*it < 0) 1140 { 1141 negetiveArray[m] = *it; 1142 m++; 1143 } 1144 else 1145 { 1146 positiveArray[n] = *it; 1147 n++; 1148 } 1149 } 1150 1151 T poMin = positiveArray[0], poMax = positiveArray[0]; 1152 T neMin = negetiveArray[0], neMax = negetiveArray[0]; 1153 1154 for (int i = 0; i < length - count; i++) 1155 { 1156 if (positiveArray[i]>poMax) 1157 { 1158 poMax = positiveArray[i]; 1159 } 1160 if (positiveArray[i] < poMin) 1161 { 1162 poMin = positiveArray[i]; 1163 } 1164 } 1165 for (int i = 0; i <count; i++) 1166 { 1167 if (negetiveArray[i]>neMax) 1168 { 1169 neMax = negetiveArray[i]; 1170 } 1171 if (negetiveArray[i] < neMin) 1172 { 1173 neMin = negetiveArray[i]; 1174 } 1175 } 1176 T poMinux = poMax - poMin; 1177 T neMinux = neMax - neMin; 1178 1179 //positive array 1180 T* positiveArrayed = new T[length - count]; 1181 T* countArrayPo = new T[poMinux + 1]; 1182 memset(countArrayPo, 0, (poMinux + 1)*sizeof(T)); 1183 1184 for (int i = 0; i < length - count; i++) 1185 { 1186 countArrayPo[positiveArray[i]-poMin]++; 1187 } 1188 for (int i = 1; i <= poMinux; i++) 1189 { 1190 countArrayPo[i] += countArrayPo[i - 1]; 1191 countArrayPo[i - 1]--; 1192 } 1193 countArrayPo[poMinux]--; 1194 for (int i = length - count - 1; i >= 0; i--) 1195 { 1196 positiveArrayed[countArrayPo[positiveArray[i] - poMin]] = positiveArray[i]; 1197 countArrayPo[positiveArray[i] - poMin]--; 1198 } 1199 //negetive value 1200 T* negetiveArrayed = new T[count]; 1201 T* countArrayNe = new T[neMinux + 1]; 1202 memset(countArrayNe, 0, (neMinux + 1)*sizeof(T)); 1203 for (int i = 0; i < count; i++) 1204 { 1205 countArrayNe[negetiveArray[i] - neMin]++; 1206 } 1207 for (int i = 1; i <= neMinux; i++) 1208 { 1209 countArrayNe[i] += countArrayNe[i - 1]; 1210 countArrayNe[i]--; 1211 } 1212 countArrayNe[neMinux]--; 1213 for (int i = count - 1; i >= 0; i--) 1214 { 1215 negetiveArrayed[countArrayNe[negetiveArray[i] - neMin]] = negetiveArray[i]; 1216 countArrayNe[negetiveArray[i] - neMin]--; 1217 } 1218 //gather two arraies 1219 m = 0, n = 0; 1220 for (it = t.begin(); it != t.end(); it++) 1221 { 1222 if (m < count) 1223 { 1224 *it = negetiveArrayed[m]; 1225 m++; 1226 } 1227 else 1228 { 1229 *it = positiveArrayed[n]; 1230 n++; 1231 } 1232 1233 } 1234 1235 delete[] positiveArray; 1236 delete[] negetiveArray; 1237 delete[] countArrayPo; 1238 delete[] countArrayNe; 1239 delete[] positiveArrayed; 1240 delete[] negetiveArrayed; 1241 } 1242 else 1243 { 1244 std::cout << "you are using non-list<int> type\n"; 1245 } 1246 } 1247 1248 void RadixSort(std::list<T>& t) 1249 { 1250 std::list<T> positiveArray; 1251 std::list<T> negetiveArray; 1252 1253 for (iterator it = t.begin(); it != t.end(); it++) 1254 { 1255 if (*it < 0) 1256 { 1257 negetiveArray.push_back(-*it); 1258 } 1259 else 1260 { 1261 positiveArray.push_back(*it); 1262 } 1263 } 1264 _RadixSort(positiveArray); 1265 _RadixSort(negetiveArray); 1266 int i = 0; 1267 iterator itNe; 1268 if (negetiveArray.size() == 0) 1269 { 1270 itNe = negetiveArray.end(); 1271 } 1272 else 1273 { 1274 itNe = --negetiveArray.end(); 1275 } 1276 for (iterator it = t.begin(), itPo = positiveArray.begin(); it != t.end(); it++) 1277 { 1278 if (i < negetiveArray.size()) 1279 { 1280 *it = -*itNe; 1281 i++; 1282 if (itNe != negetiveArray.begin()) 1283 { 1284 itNe--; 1285 } 1286 } 1287 else 1288 { 1289 *it = *itPo; 1290 itPo++; 1291 } 1292 } 1293 } 1294 1295 void BucketSort(std::list<T>& t) 1296 { 1297 int length = t.size(); 1298 T max = *(t.begin()), min = *(t.begin()); 1299 for (iterator it = t.begin(); it != t.end(); it++) 1300 { 1301 if (*it > max) 1302 { 1303 max = *it; 1304 } 1305 if (*it < min) 1306 { 1307 min = *it; 1308 } 1309 } 1310 int minux = max - min+1; 1311 std::vector<T>* colArray = new std::vector<T>[length]; 1312 for (iterator it = t.begin(); it != t.end(); it++) 1313 { 1314 int index = (*it - min)*length / minux; 1315 colArray[index].push_back(*it); 1316 } 1317 for (int i = 0; i < length; i++) 1318 { 1319 Sort<std::vector<T>> s; 1320 s.InsertSort(colArray[i]); 1321 } 1322 int m = 0; 1323 //the border condition annoys me a lot! 1324 for (iterator it = t.begin(); it != t.end(); m++) 1325 { 1326 for (std::vector<T>::iterator itCol = colArray[m].begin(); itCol != colArray[m].end(); itCol++) 1327 { 1328 *it = *itCol; 1329 it++; 1330 } 1331 } 1332 } 1333 1334 private: 1335 void _MergeSort(std::list<T>& t, int a, int b) 1336 { 1337 if (a<b) 1338 { 1339 int c = (a + b) / 2; 1340 _MergeSort(t, a, c); 1341 _MergeSort(t, c + 1, b); 1342 1343 std::list<T>::iterator ita = t.begin(); 1344 std::list<T>::iterator itc = t.begin(); 1345 std::list<T>::iterator itb = t.begin(); 1346 for (int i = 0; i <= b; i++) 1347 { 1348 if (i<a) 1349 { 1350 ita++; 1351 } 1352 if (i<c) 1353 { 1354 itc++; 1355 } 1356 if (i<b) 1357 { 1358 itb++; 1359 } 1360 } 1361 Merge(t, ita, itc, itb); 1362 } 1363 1364 } 1365 1366 //Here we can't directly use the std::list<T>::iterator, use the typedef to replace it 1367 //compiler of ms 1368 void Merge(std::list<T>& t, iterator a, iterator c, iterator b) 1369 { 1370 std::list<T> temp1; 1371 std::list<T>::iterator nothing = ++c; 1372 c--; 1373 for (std::list<T>::iterator it = a; it != nothing; it++) 1374 { 1375 temp1.push_back(*it); 1376 } 1377 temp1.push_back(2147483647); 1378 std::list<T> temp2; 1379 std::list<T>::iterator something = ++b; 1380 b--; 1381 for (std::list<T>::iterator it = nothing; it != something; it++) 1382 { 1383 temp2.push_back(*it); 1384 } 1385 temp2.push_back(2147483647); 1386 1387 1388 std::list<T>::iterator itTemp1 = temp1.begin(); 1389 std::list<T>::iterator itTemp2 = temp2.begin(); 1390 for (std::list<T>::iterator it = a; it != something; it++) 1391 { 1392 if (*itTemp1 > *itTemp2) 1393 { 1394 *it = *itTemp2; 1395 itTemp2++; 1396 } 1397 else 1398 { 1399 *it = *itTemp1; 1400 itTemp1++; 1401 } 1402 } 1403 } 1404 1405 iterator IteratorIncrease(std::list<T>& t, iterator it,int i) 1406 { 1407 iterator tempIt = it; 1408 for (int index = 0; index < i; index++) 1409 { 1410 if (tempIt == t.end()--) 1411 { 1412 return t.end(); 1413 } 1414 tempIt++; 1415 } 1416 return tempIt; 1417 } 1418 1419 iterator IteratorDecrese(std::list<T>& t, iterator it, int i) 1420 { 1421 iterator tempIt = it; 1422 for (int index = 0; index < i; i++) 1423 { 1424 if (tempIt == t.begin()) 1425 { 1426 std::cout << "out of range with iterator in decrese"; 1427 return t.end(); 1428 } 1429 else 1430 { 1431 tempIt--; 1432 } 1433 } 1434 return tempIt; 1435 } 1436 1437 int GetIteratorPosition(std::list<T>& t, iterator it) 1438 { 1439 int position = -1; 1440 iterator tempIt = t.begin(); 1441 for (tempIt; tempIt != t.end(); tempIt++) 1442 { 1443 position++; 1444 if (tempIt == it) 1445 { 1446 break; 1447 } 1448 } 1449 if (position >= t.size()) 1450 { 1451 return -1; 1452 } 1453 return position; 1454 } 1455 1456 int GetLeftChild(std::list<T>& t, iterator it) 1457 { 1458 int number = -1; 1459 iterator tempIt; 1460 for (tempIt = t.begin(); tempIt != t.end(); tempIt++) 1461 { 1462 number++; 1463 if (tempIt == it) 1464 { 1465 break; 1466 } 1467 } 1468 if (number >= t.size()) 1469 { 1470 //the it is not one of the t'iterator; 1471 return NULL; 1472 } 1473 1474 int leftChild = ((number + 1) << 1) - 1; 1475 return leftChild; 1476 } 1477 1478 int GetRightChild(std::list<T>& t, iterator it) 1479 { 1480 int number = -1; 1481 iterator tempIt; 1482 for (tempIt = t.begin(); tempIt != t.end(); tempIt++) 1483 { 1484 number++; 1485 if (tempIt == it) 1486 { 1487 break; 1488 } 1489 } 1490 if (number >= t.size()) 1491 { 1492 //the it is not one of the t'iterator; 1493 return NULL; 1494 } 1495 1496 int RightChild = (number + 1) << 1; 1497 return RightChild; 1498 } 1499 1500 void MaxHeapify(std::list<T>& t, iterator it, int length) 1501 { 1502 //iterator tempIt = IteratorIncrease(t, t.begin(), length); 1503 int leftChild = GetLeftChild(t, it); 1504 int rightChild = GetRightChild(t, it); 1505 int i = GetIteratorPosition(t, it); 1506 1507 iterator itLeft = IteratorIncrease(t, t.begin(), leftChild); 1508 iterator itRight = IteratorIncrease(t, t.begin(), rightChild); 1509 1510 int largest = 0; 1511 T tLargest; 1512 if (leftChild <= length && *itLeft > *it) 1513 { 1514 largest = leftChild; 1515 tLargest = *itLeft; 1516 } 1517 else 1518 { 1519 largest = i; 1520 tLargest = *it; 1521 } 1522 1523 if (rightChild <= length && *itRight > tLargest) 1524 { 1525 largest = rightChild; 1526 tLargest = *itRight; 1527 } 1528 1529 if (largest != i) 1530 { 1531 T temp = *it; 1532 *it = tLargest; 1533 1534 if (largest == leftChild) 1535 { 1536 *itLeft = temp; 1537 MaxHeapify(t, itLeft, length); 1538 } 1539 else 1540 { 1541 *itRight = temp; 1542 MaxHeapify(t, itRight, length); 1543 } 1544 } 1545 } 1546 1547 void BuildHeap(std::list<T>& t) 1548 { 1549 for (int i = (t.size() - 1) / 2; i >= 0; i--) 1550 { 1551 iterator temp = IteratorIncrease(t, t.begin(), i); 1552 MaxHeapify(t, temp, t.size()-1); 1553 } 1554 } 1555 1556 void _QuickSort(std::list<T>& t, int a, int b) 1557 { 1558 if (a < b) 1559 { 1560 int s = Partition(t, a, b); 1561 _QuickSort(t, a, s - 1); 1562 _QuickSort(t, s + 1, b); 1563 } 1564 } 1565 1566 int Partition(std::list<T>& t, int a, int b) 1567 { 1568 iterator l = IteratorIncrease(t, t.begin(), a); 1569 iterator r = IteratorIncrease(t, t.begin(), b); 1570 1571 T split = *l; 1572 while (a < b && l != t.end() && r != t.end()) 1573 { 1574 while (a<b && *r>split) 1575 { 1576 b--; 1577 r--; 1578 } 1579 T temp = *r; 1580 *r = *l; 1581 *l = temp; 1582 1583 while (a<b && *l < split) 1584 { 1585 a++; 1586 l++; 1587 } 1588 temp = *l; 1589 *l = *r; 1590 *r = temp; 1591 } 1592 return a; 1593 } 1594 1595 inline int GetNIndex(int t, int i) 1596 { 1597 return (t % (int)pow(10, i + 1) - t % (int)pow(10, i)) / pow(10, i); 1598 } 1599 1600 void _RadixSort(std::list<T>& t) 1601 { 1602 int length = t.size(); 1603 if (length == 0) 1604 { 1605 return; 1606 } 1607 T max = *t.begin(); 1608 int count = 0; 1609 for (iterator it = t.begin(); it != t.end(); it++) 1610 { 1611 if (*it > max) 1612 { 1613 max = *it; 1614 } 1615 } 1616 int k = max / pow(10, count); 1617 while (k != 0) 1618 { 1619 count++; 1620 k = max / pow(10, count); 1621 } 1622 1623 T* tempArray = new int[length]; 1624 for (int i = 0; i < count; i++) 1625 { 1626 int* positionArray = new int[length]; 1627 int* countArray = new int[10]; 1628 memset(countArray, 0, 10 * sizeof(int)); 1629 1630 iterator it = t.begin(); 1631 for (int j = 0; j < length; j++) 1632 { 1633 positionArray[j] = GetNIndex(*it, i); 1634 it++; 1635 } 1636 1637 for (int m = 0; m < length; m++) 1638 { 1639 countArray[positionArray[m]]++; 1640 } 1641 for (int m = 1; m < 10; m++) 1642 { 1643 countArray[m] += countArray[m - 1]; 1644 countArray[m - 1]--; 1645 } 1646 countArray[9]--; 1647 // 1648 it = --t.end(); 1649 for (int m = length - 1; m >= 0; m--) 1650 { 1651 tempArray[countArray[positionArray[m]]] = *it; 1652 countArray[positionArray[m]]--; 1653 if (it != t.begin()) 1654 { 1655 it--; 1656 } 1657 } 1658 int m = 0; 1659 for (it = t.begin(); it != t.end(); it++) 1660 { 1661 *it = tempArray[m]; 1662 m++; 1663 } 1664 delete[] positionArray; 1665 delete[] countArray; 1666 } 1667 delete[] tempArray; 1668 } 1669 }; 1670 1671 #pragma endregion
过段时间再贴上树这种树(非二叉树)结构的模板,其格式也会向标准模板靠齐,基本功能已经具有,但是还不够强大,远没有达到通用的标准。其存储结构是孩子兄弟存储法,针对树的前序遍历已经写好。