快速排序算法的思想:
1.选取数组中的一个基准元素pivot
2.分区:将这个数组中小于基准元素的元素移动到基准元素左边,数组中大于基准元素的元素移动到基准元素右边
3.对分成后的两区重复步骤2,直至两区间中只剩下一个元素
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 快速排序_代码展示
{
internal class Program
{
/// <summary>
/// 快速排序的平均算法复杂度是O(nlogn),最坏情况是O(n ^ 2)
/// </summary>
static void quicksort(int[] a, int low, int high)
//a是待排序的数组,low是数组的起始下标,high是数组的结束下标
{
int i = a[low];//指定i指针
int j = a[high];//指定j指针
int pivot = a[low];
//选择基准元素,一般选择起始下标的元素作为基准元素
while (i < j)
//判断起始位置指针所指向的元素是否小于结束位置指针所指向的元素
{
//如果起始元素大小小于结束位置元素并且j指针指向的元素大小小于基准元素
//因为选取的是起始下标的元素作为基准元素,所以先移动j指针
while (i < j && a[j] > pivot)
{
--j;//指针向左移动
a[i] = a[j];
//把j指针移动前所指向的元素交换到i指针指向的空元素
//(注意:基准元素pivot已经把i指针指向的起始下标的元素取走,
所以i指针此时指向的元素为空)
}
//刚刚j指针移动,现在轮到i指针移动。刚刚j指针移动并赋值给i指针,
所以i指针有值
//如果起始元素大小小于结束位置元素并且i指针指向的元素大小小于基准元素
while (i < j && a[i] < pivot)
{
++i;//指针向右移动
a[j] = a[i];
//当指针i遇到比基准元素大的元素时,把i指针指向的元素赋值给j指针
指向的空元素
//刚刚j指针移动并赋值给i指针,所以j指针此时指向的元素为空
}
}
a[i] = pivot;
//当两区已分配完,即a[i]=a[j],此时将基准元素pivot赋值给i,j指针指向的空元素
quicksort(a, low, i - 1);//开始左边的快排
quicksort(a, j + 1, high);//开始右边的快排
}
}
}
纯代码展示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 快速排序_代码展示
{
internal class Program
{
/// <summary>
/// 快速排序的平均算法复杂度是O(nlogn),最坏情况是O(n ^ 2)
/// </summary>
static void quicksort(int[] a, int low, int high)
{
int i = a[low];
int j = a[high];
int pivot = a[low];
while (i < j)
{
while (i < j && a[j] > pivot)
{
--j;
a[i] = a[j];
}
while (i < j && a[i] < pivot)
{
++i;
a[j] = a[i];
}
}
a[i] = pivot;
quicksort(a, low, i - 1);
quicksort(a, j + 1, high);
}
}
}
注意:
1.快速排序中第一次指针移动时 j 指针移动可以一直移动,不仅限于只移动一次,直到遇见 j 指针所指向的元素小于基准元素,此时把 j 指针指向的值赋值给还未移动的 i 指针所指向的空元素。
2.快速排序只适用于无须的数组,不适用与有序或基本有序的数组。数组越乱,排序越快。
3.(面试常问)快速排序的平均算法复杂度是O(nlogn),最坏情况是O(n ^ 2)
4.快速排序不稳定!