快速排序是对冒泡排序的一种改进。
其基本思想是基于分治法:在待排序表L[1...n]中任取一个元素pivot作为基准,通过一趟排序将待排序表中划分为独立的两部分L[1...k-1]和L[k+1....n],使得L[1...k-1]中所有元素小于等于pivot,L[k+1....n]中所有元素大于等于pivot,则pivot放在了其最终位置L(k)上,这个过程称为一趟快速排序。而后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或者空为止,即所有元素放在了其最终位置上。
快速排序的代码:
int Partition(int a[], int low, int high)
{
int pivot = a[low];//将当前表中第一元素设为枢轴值,对表进行划分
while (low < high)
{
while (low < high && a[high] > pivot)
--high;
a[low] = a[high];//将比枢轴值小的元素移动到左端
while (low < high && a[low] < pivot)
++low;
a[high] = a[low];//将比枢轴值大的元素移动到右端
}
a[low] = pivot;//枢轴元素存放到最终位置
return low;//返回存放枢轴的最终位置
}
void QuickSort(int a[], int low, int high)
{
if (low < high)//边界条件,即递归跳出的条件
{
int pivotpos = Partition(a, low, high);//划分
QuickSort(a, low, pivotpos - 1);//依次对两个子表进行递归排序
QuickSort(a, pivotpos + 1, high);
}
}
int main()
{
int n = 8;
int a[20];
for (int i = 0; i < n; ++i)
{
cout << "Please enter a number : ";
cin >> a[i];
}
QuickSort(a, 0, 7);
for (int i = 0; i < n; ++i)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
快速排序的分治partition过程有两种方法。
(1)两个下标分别从首尾向中间扫描的方法
int Partition(int a[], int low, int high)
{
int pivot = a[low];//将当前表中第一元素设为枢轴值,对表进行划分
while (low < high)
{
while (low < high && a[high] > pivot)
--high;
a[low] = a[high];//将比枢轴值小的元素移动到左端
while (low < high && a[low] < pivot)
++low;
a[high] = a[low];//将比枢轴值大的元素移动到右端
}
a[low] = pivot;//枢轴元素存放到最终位置
return low;//返回存放枢轴的最终位置
}
int Partition(int a[], int low, int high)
{
int x = a[high];//以最后一个元素为枢轴值
int i = low;
for (int j = low; j < high; ++j)
{
if (a[j] <= x)
{
swap(a[i], a[j]);
++i;
}
}
swap(a[i], a[high]);
return i;
}
快速排序算法的性能分析如下:
空间效率:由于快速排序是递归地,需要借助一个递归工作栈来保存每一层递归调用的必要信息,其容量应与递归调用的最大深度一致。最好情况下为[log2(n+1)];最坏情况下,因为要进行n-1次递归调用,所以栈的深度为O(n);平均情况下,栈的深度为O(log2(n))。因而空间复杂度在最坏情况下为O(n),平均情况下为O(log2(n))。
时间效率:快速排序的运行时间与划分是否对称有关,而后者又与具体使用的划分算法有关。快速排序的最坏情况发生在两个区域分别包含n-1个元素和0个元素时,这种最大程度的不对称如发生在每一层递归上,就得到最坏情况下的时间复杂度为O(n^2)。
在最理性的状态下,也即partition()可能做到最平衡的划分中,得到的两个子问题的大小都不可能大于n/2,在这种情况下,快速排序的运行速度将大大提升,此时,时间复杂度为O(nlog2(n))。好在快速排序平均情况下运行时间与其最佳情况下的运行时间很接近,而不是接近最坏情况下的运行时间。
快速排序是所有内部排序算法中平均性能最优的排序算法。
稳定性:快速排序是一个不稳定的排序方法。