1.冒泡排序(时间复杂度为 O(N2))
原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,
这样一趟过去后,最大或最小的数字被交换到了最后一位;重复此动作直到排好序为止;
先来cv一个动图看看效果:
void BubbleSort(vector<int>& Vector) { for (int i = 0; i < Vector.size(); ++i) { for (int j = 0; j < Vector.size() - i - 1; ++j) { if (Vector[j] > Vector[j + 1]) swap(Vector[j], Vector[j + 1]); } } }
/*优化*/ void OptimizeBubbleSort(vector<int>& Vector) { int index = Vector.size() - 1; bool sign = true; while (index && sign) { int tmp = -1; for (int i = 0; i < index; ++i) { if (Vector[i] > Vector[i + 1]) { swap(Vector[i], Vector[i + 1]); tmp = i; } } tmp > 0 ? index = tmp : sign = false; } }
这里奉上一篇关于冒泡排序的博文(超赞): http://blog.csdn.net/lemon_tree12138/article/details/50591859
2.快速排序
快速排序也是一种采用分治法解决问题的一个典型应用。在很多编程语言中,对数组,列表进行的非稳定排序在内部实现中都使用的是快速排序。
借鉴前辈们的动图看下效果先:
快速排序的基本思想如下:
- 对数组进行随机化。
- 每次从数列中取出最后一个数作为参照;
- 将比这个数大或者等于的数放到它的右边,小于它的数放到它的左边。
- 再对左右区间重复第三步,直到各区间只有一个数。
举个栗子:
/*方式一:见上图 ↑↑↑↑↑↑*/
int _QuickSort(vector<int>& Vector, int left, int right) { int middle = left + (right - left) / 2; /*优化一:三数取中*/ int MaxNumber = Max(Vector[left],Max(Vector[middle], Vector[right])); int MinNumber = Min(Vector[left],Min(Vector[middle], Vector[right])); if (Vector[left] > MinNumber && Vector[left] < MaxNumber) swap(Vector[left], Vector[right]); else if (Vector[middle] > MinNumber && Vector[middle] < MaxNumber) swap(Vector[middle],Vector[right]); int begin = left, end = right - 1; int key = Vector[right]; while (begin < end) { while (begin < end && Vector[begin] < key) ++begin; while (begin < end && Vector[end] >= key) --end; swap(Vector[begin], Vector[end]); } if (Vector[begin] > key) { swap(Vector[begin], Vector[right]); return begin; } else { return right; } } /*方式二;挖坑法*/ int _QuickSort(vector<int>& Vector, int left, int right) { int begin = left, end = right; int key = Vector[right]; while (begin < end) { while (begin < end && Vector[begin] < key) ++begin; Vector[end] = Vector[begin]; while (begin < end &&Vector[end] >= key) --end; Vector[begin] = Vector[end]; } Vector[begin] = key; return begin; } /*方式三:前后指针法*/ int _QuickSort(vector<int>& Vector, int left, int right) { int begin = left, small = left - 1, end = right; int key = Vector[right]; while (begin < end) { if (Vector[begin] < key) { ++small; swap(Vector[small], Vector[begin]); } ++begin; } swap(Vector[++small ], Vector[end]); return small; }
void QuickSort(vector<int>& Vector, int left, int right) { if (right - left > 13) //优化二:当区间小到一定程度时,使用插入排序 { int middle = _QuickSort(Vector, left, right); QuickSort(Vector, left, middle - 1); QuickSort(Vector, middle+1, right); } else { //插入排序 InsertSort(Vector, left, right); } } /*插入排序*/ void InsertSort(vector<int>& Vector, int left, int right) { for (int i = left; i<right; ++i) { int end = i; int key = Vector[end + 1]; while (end >= left && Vector[end] > key) { Vector[end + 1] = Vector[end]; --end; } Vector[end + 1] = key; } }
算法分析:
- 在最好的情况下,快速排序只需要大约nlgn次比较操作,在最坏的情况下需要大约1/2 n2 次比较操作。
- 在最好的情况下,每次的划分都会恰好从中间将序列划分开来,那么只需要lgn次划分即可划分完成,每一次划分都需要比较N次。
- 在最坏的情况下,即序列已经排好序的情况下,每次划分都恰好把数组划分成了0,n两部分,那么需要n次划分,但是比较的次数则变成了n, n-1, n-2,….1, 所以整个比较次数约 为 nnndf n(n-1)/2~n2/2.
- 平均情况下,快速排序需要大约1.39NlgN次比较,这比合并排序多了39%的比较,但是由于涉及了较少的数据交换和移动操作,他要比合并排序更快。
- 快速排序是非稳定性排序。