基本思想:
1)选择一个关键字,通常选择最后一个元素,
2)通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比关键字值小。另一部分记录的 元素值比关键字的值大。
3)此时关键字在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
分析:
快速排序是通常被认为在同数量级(O(nlog2n))的排序方法中平均性能最好的。但若初始序列有序或基本有序时,快排序蜕化为冒泡排序(O(n^2))。若关键字的值设的接近最大值或最小值时会使时间复杂度变大,所以我在实现时求出此范围的中间值作为关键字。
一、采用递归思想的快速排序
#pragma once #include<assert.h> #include<iostream> using namespace std; int GetmidIndex(int *a, int left, int right)//得到中间值的下标 { assert(a); int mid = left+(right-left)/2; if (a[left] < a[right]) { if (a[mid] < a[left]) return left; else if (a[mid] < a[right]) return mid; else return right; } else { if (a[mid] < a[right]) return right; else if (mid < a[right]) return mid; else return left; } } int PartionSort1(int*a, int left, int right)//部分排序,使关键字左边值比关键字小,关键字右边值比关键字大,返回关键字所在位置的下标 { assert(a); int mid = GetmidIndex(a, left, right); if (mid != right) { swap(a[mid], a[right]);//将中间值交换到此范围最右边,提高效率 } int key = a[right];//一般将最右边的值设为关键字 int begin = left; int end = right - 1; while(begin<end) { while (begin < end&&a[begin] <= key) { ++begin; } while (begin < end&&a[end] >= key) { --end; } if (begin < end) { swap(a[begin], a[end]); } } if (a[right] <a[begin]) { swap(a[begin], a[right]); return begin; } else return right; } void QuickSort1(int *a, int left, int right)//递归 { assert(a); if (left < right) { int boundary = PartionSort1(a, left, right);//关键字所在位置的下标 QuickSort1(a, left, boundary - 1); QuickSort1(a, boundary + 1, right); } }
二、采用栈的思想的快速排序
void QuickSort_NoR(int*a,int left,int right) { stack<int> s; if (left < right) { int mid = PartionSort1(a, left, right);//返回关键字所在下标 if (left < mid - 1) { s.push(left); s.push(mid - 1);//将比关键字小的范围入栈 } if (mid + 1 < right) { s.push(mid + 1); s.push(right);//将比关键字大的范围入栈 } while (!s.empty()) { int end= s.top(); s.pop(); int begin = s.top(); s.pop(); mid = PartionSort(a, begin, end); if (begin < mid - 1) { s.push(begin); s.push(mid - 1); } if (mid + 1 < end) { s.push(mid + 1); s.push(end); } } } }