标签:
1.首先当然是插入排序啦,算法的时间复杂度其实是O(N^2)的
先来个一般的描述:
1 template<typename Comparable> 2 void insertSort(vector<Comparable> & a) 3 { 4 int j; 5 for (int p = 1; p < a.size(); p++) 6 { 7 Comparable tmp = a[p]; 8 for (int j = p - 1; j > 0 && tmp < a[j - 1]; j--) 9 a[j] = a[j - 1]; 10 a[j] = tmp; 11 } 12 }
再就是stl的描述,主要分为四个部分,比较麻烦
1 template <typename Iterator> 2 void insertionSort(const Iterator & begin, const Iterator & end) 3 { 4 if (begin != end) 5 insertSortionHelp(begin, end, *begin);//用于解析类型 6 } 7 8 template <typename Iterator, typename Object> 9 void insertionSortHelp(const Iterator & begin, const Iterator & end, const Object & obj) 10 { 11 insertionSort(begin, end, less<Object>()); 12 } 13 14 15 template <typename Iterator, typename Comparator> 16 void insertionSort(const Iterator & begin, const Iterator & end, Comparator lessThan) 17 { 18 if (begin ! = end) 19 insertionSort(begin, end, lessThan, *begin); 20 } 21 22 template <typename Iterator, typename Comparator, typename Object> 23 void insertionSort(const Iterator & begin, const Iterator & end, Comparator lessThan, const Object & obj) 24 { 25 Iterator j; 26 for (Iterator p = begin + 1; p != end; p++) 27 { 28 Object tmp = *p; 29 for (j = p; j != begin && lessThan(tmp, *(j - 1)); --j) 30 *j = *(j - 1); 31 *j = tmp; 32 } 33 //这整个4个函数组成了一个STL,很麻烦所以一般不用STL界面 34 35 }
2.第二个就是希尔排序,希尔排序其实相当于插入排序的不同间隔的版本,同样可以证明得知其算法复杂度为O(N^2)的。
1 template<typename Comparable> 2 void shellSort(vector<Comparable > & a) 3 { 4 for (gap = a.size() / 2; gap > 0; gap /= 2) 5 { 6 for (int i = gap; i < a.size(); i++) 7 { 8 Comparable tmp = a[i]; 9 int j = i; 10 for (; j > gap && tmp < a[j - gap]; j -= gap) 11 a[j] = a[j - gap]; 12 a[j] = tmp; 13 } 14 } 15 }
3.在下面就是堆排序
堆排序的算法思想其实很简单,先是建立一个堆,可以先按照逆序建堆,然后在一个一个的把堆中最大的元素,放到数组的最后一个位置,后面其实相当于还要建立N次堆。
要点就是不停的建立新的堆,可以证明堆排序的算法时间复杂度为Nlog(N)的。
1 template <typename Comparable> 2 void heapSort(vector<Comparable> & a) 3 { 4 for (int i = a.size() / 2; i > 0; i--) 5 percDown(a, i, a.size()); //首先是建堆 6 for (int j = a.size() - 1; j > 0; j--) 7 { //这一步从堆中删除最大值到vector的末尾,这样完成了排序 8 swap(a[0], a[j]); 9 percDown(a, 0, j); 10 } 11 } 12 13 inline int leftChild(int i) 14 { 15 return 2 * i + 1; 16 } 17 18 template<typename Comparable> 19 void percDown(vector<Comparable> & a, int i, int j) 20 { 21 int child; 22 Comparable tmp; 23 24 for (tmp = a[i], leftChild(i) < n; i = child) 25 { 26 child = leftChild(i); 27 if (child != n - 1 && a[child] < a[child + 1]) 28 child++; 29 if (tmp < a[child]) 30 a[i] = a[child]; 31 else 32 break; 33 } 34 a[i] = tmp; 35 }
4.然后就是归并排序
归并排序主要使用了递归的思想,即分治策略,可以证明其算法时间复杂度为Nlog(N)的。
1 template<typename Comparable> 2 void mergeSort(vector<Comparable & a>) 3 { 4 vector<Comparable> tmpArray(a.size()); 5 mergeSort(a, tmpArray, 0, a.size() - 1); 6 } 7 8 template <typename Comparable> 9 void mergeSort(vector<Comparable> & a, vector<Comparable> & b, int left, int right) 10 { 11 if (left < right) 12 { 13 int center = (left + right) / 2; 14 mergeSort(a, tmpArray, left, center); 15 mergeSort(a, tmpArray, center + 1, right); 16 merge(a, tmpArray, left, center + 1, right); 17 } 18 } 19 20 template<typename Comparable> 21 void merge(vector<Comparable> & a, vector<Comparable> tmpArray, int leftPos, int rightPos, int rightEnd) 22 { 23 int leftEnd = rightPos - 1; 24 int tmpPos = leftPos; 25 int numElements = rightEnd - leftPos + 1; 26 while (leftPos < leftEnd && rightPos < rightEnd) 27 { 28 if (a[leftPos] <= a[rightPos]) 29 tmpArray[tmpPos++] = a[leftPos++]; 30 else 31 tmpArray[tmpPos++] = a[rightPos++]; 32 } 33 while (leftPos <= leftEnd) 34 tmpArray[tmpPos++] = a[leftPos++]; 35 while (rightPos <= rightEnd) 36 tmpArray[tmppos++] = a[rightPos++]; 37 38 for (int i = 0; i < numElements; i++, rightEnd--)//这一步拷贝的方法值得注意 39 a[rightEnd] = tmpArray[rightEnd]; 40 }
5.最后就是大名鼎鼎的快排算法,其算法复杂度最大不超过O(N^2),平均值为O(Nlog(N))
1 template<typename Comparable> 2 void quickSort(vector<Comparable> & a) 3 { 4 quickSort(a, 0, a.size() - 1); 5 }
1 //首先是枢纽元的选取 2 template<typename Comparable> 3 const Comparable & median3(vector<Comparable> & a, int left, int right) 4 { 5 int center = (left + right) / 2; 6 if (a[center] < a[left]) 7 swap(a[center], a[left]); 8 if (a[right] < a[left]) //将最小的元素放到vector的最左边,符合要求 9 swap(a[left], a[right]); 10 if (a[right] < a[center]) //将最大的元素放到vector的最右边,这也符合要求 11 swap(a[center], a[right]); 12 13 swap(a[center], a[right - 1]); //将枢纽元放在最右边左侧一个的位置上,符合要求 14 return a[right - 1]; 15 } 16 17 template <typename Comparable> 18 void quickSort(vector<Comparable> & a, int left, int right) 19 { 20 if (left + 10 <= right) 21 { 22 Comparable pivot = median3(a, left, right); 23 int i = left; j = right - 1; 24 for (;;) 25 { 26 while (a[++i] < pivot){} 27 while (a[--j] > pivot){} 28 if (i < j) //如果i,j的前后顺序还没有交换,那么这一轮块排还没有结束 29 swap(a[i], a[j]) 30 else break; 31 } 32 swap(a[i], a[right - 1]); 33 quickSort(a, left, i - 1); 34 quickSort(a, i + 1, right); 35 } 36 else 37 insertionSort(a, left, right);<span style="white-space:pre"> </span>//对于小数组,那么采取插入排序性能较好 38 }<pre name="code" class="cpp">template<typename Comparable> 39 void quickSort(vector<Comparable> & a) 40 { 41 quickSort(a, 0, a.size() - 1); 42 }
1 简单介绍一个快排算法的展开:快速选择其代码段如下所示,其实相当于快速选择找一个固定的数的版本 2 template<typename Comparable> 3 void quickSort(vector<Comparable> & a) 4 { 5 quickSort(a, 0, a.size() - 1); 6 } 7 //首先是枢纽元的选取 8 template<typename Comparable> 9 const Comparable & median3(vector<Comparable> & a, int left, int right) 10 { 11 int center = (left + right) / 2; 12 if (a[center] < a[left]) 13 swap(a[center], a[left]); 14 if (a[right] < a[left]) //将最小的元素放到vector的最左边,符合要求 15 swap(a[left], a[right]); 16 if (a[right] < a[center]) //将最大的元素放到vector的最右边,这也符合要求 17 swap(a[center], a[right]); 18 19 swap(a[center], a[right - 1]); //将枢纽元放在最右边左侧一个的位置上,符合要求 20 return a[right - 1]; 21 } 22 template <typename Comparable> 23 void quickSelect(vector<Comparable> & a, int left, int right, int k) 24 { 25 if (left + 10 <= right) 26 { 27 Comparable pivot = median3(a, left, right); 28 int i = left; j = right - 1; 29 for (;;) 30 { 31 while (a[++i] < pivot){} 32 while (a[--j] > pivot){} 33 if (i < j) //如果i,j的前后顺序还没有交换,那么这一轮块排还没有结束 34 swap(a[i], a[j]) 35 else break; 36 } 37 swap(a[i], a[right - 1]); 38 if(k <= i) 39 quickSelect(a, left, i - 1, k); 40 else if(k > i+1) 41 quickSelect(a, i + 1, right, k); 42 } 43 else 44 insertionSort(a, left, right); 45 }
6.对于大元素的数组排序,由于不断移动的成本很高,所以一般会使用移动指针的方式代替直接的大元素的移动
1 //首先应该声明一个指针类,其中应该包含比较方法,在用这个指针类去调用quicksort就行了 2 template<typename Comparable> 3 class Pointer 4 { 5 private: 6 Comparable * pointee; 7 public: 8 Pointer(Comparable * rhs = NULL) : pointee(rhs){} 9 10 bool operator<(const Pointer & rhs)cosnt 11 { 12 return *pointee < *rhs.pointee; 13 } 14 15 operator Comparable*()const<span style="white-space:pre"> </span>//转换符号,使得完成从pointer<Comparable>da使得可以 16 {<span style="white-space:pre"> </span>//直接使用*pointer,这里已经有着隐含着的Comparator*了 17 <span style="white-space:pre"> </span>{<span style="white-space:pre"> </span>//定义了这个符号之后就可以完成Pointer与Comparable*之间的双向转换!! 18 <span style="white-space:pre"> </span>return *pointee; 19 <span style="white-space:pre"> </span>} 20 };
1 template<typename Comparable> 2 void largeObjectSort(vector<Comparable> & a) 3 { 4 vector<Pointer<Comparable>> p(a.size()); 5 int i, j, next; 6 7 for (i = 0; i < a.size(); i++) 8 p[i] = &a[i]; 9 10 quickSort(p); 11 12 //下面再依靠指针指向的情况来将数组重新来排列,其中使用到了滑动算法 13 for (i = 0; i < a.size(); i++) 14 if (p[i] != a[i]) 15 { 16 Comparable tmp = a[i]; 17 for (j = i; p[j] != &a[i]; j = nextj) 18 { 19 nextj = p[j] - &a[0]; //这里使用的滑动算法,可以自己画图演示一下 20 a[i] = *p[j]; 21 p[j] = &a[j]; 22 } 23 a[j] = tmp; 24 p[j] = &a[j]; 25 } 26 }
//大量元素的排序最好直接使用快排算法,注意不要图省事将第一个元素作为枢纽元
//如果考虑编程的简洁性可以使用希尔排序
//堆排序比希尔排序是要慢的
//插入排序一般只用在小或者是基本上已经排好序的输入数据上
//归并排序较为麻烦而且对于CPU的主存排序性能不一定有快速排序好
标签:
原文地址:http://www.cnblogs.com/-wang-cheng/p/4874254.html