快速排序原理 C# 递归
快速排序是一种二分法排序方法,实际上理论上真正最快的排序方法是黄金分割法,但是这在计算机上是很难实现的,因此快速排序也算是兼顾了速度与占用内存的一种较好的排序方式:
快速排序的实现步骤大概如下:
【假设我们需要将一个数组按照从小到大的顺序排列】
1、选最左侧的数作为一个基准数,并从左–>右 和 从右–>左 分别寻找比基准数大 和 比基准数小的数,一定是先从右边先找,这是因为我们选择的是最左侧的数作为基准数,最后要将这个数放到最中间,而如果先从左边找,那么当左右相遇时候就可能出现中间数实际上比最左边的基准数大,这样就出BUG了,因此一定是先从右边寻找,然后找到一个小于基准数时就停下来,这时候,再从左边开始寻找,然后当找一个比基准数大的数就停下来,一直这样,直到左右寻找相遇。相遇时就将这个相遇点的数和第一个基准数交换。
2、经过了第一步就将数组分成了 2 份,相遇点左边一份 ,相遇点右边一份,然后在对着两部分重复第一步…
3、最后,当分到每一小份左右只有一个数的时候就完成了快速排序。
其中第二步涉及到递归过程,当然也是很好理解的,只要这个过程类似并且是具有递进关系的都可以用递归。
就像切蛋糕一样,先一分为二,再一分为二,再一分为二,切的这个过程就是一个类似的过程,而越分越小就是一个递进的关系。
快速排序的时间复杂度为:O(N*log(N))
下面贴出代码,这样理解更容易:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FastSort
{
class Program
{
static double[] RequireSortNum;
static void Main(string[] args)
{
NumInit();
Console.WriteLine("初始数据:");
ShowCurrentSort();
FastSort(0, 99);
Console.WriteLine("快排序后数据:");
ShowCurrentSort();
Console.Read();
}
static void FastSort(int LeftIndex,int RightIndex)
{
if (LeftIndex > RightIndex)
return;
double BaseNum = RequireSortNum[LeftIndex];//将第一个点假设为基准点
int CurrentRightIndex = RightIndex;//当前询问的右侧坐标
int CurrentLeftIndex = LeftIndex;//当前询问的左侧坐标
double temp;//交换的暂存值
while (CurrentRightIndex != CurrentLeftIndex)//已知要询到左右两边相遇 这时候相遇点就是基准点的位置
{
while (RequireSortNum[CurrentRightIndex] >= BaseNum && CurrentRightIndex > CurrentLeftIndex)
{
CurrentRightIndex--;
}
while (RequireSortNum[CurrentLeftIndex] < BaseNum && CurrentRightIndex > CurrentLeftIndex)
{
CurrentLeftIndex++;
}
if (CurrentRightIndex > CurrentLeftIndex)//如果两边没有相遇就交换
{
temp = RequireSortNum[CurrentRightIndex];
RequireSortNum[CurrentRightIndex] = RequireSortNum[CurrentLeftIndex];
RequireSortNum[CurrentLeftIndex] = temp;
}
}
//当两边相遇了 就将第一个基准点 放到中间位置
RequireSortNum[LeftIndex] = RequireSortNum[CurrentRightIndex];
RequireSortNum[CurrentRightIndex] = BaseNum;//将第一个点【这个点就是基准点】 放到中间位置
//这是因为一开始是先从右边开始轮询的,最左边的被选做基准点的数并没有到正确的中间位置
//这一步正是让这个点到它该去的位置
FastSort(LeftIndex,CurrentLeftIndex-1);//排列中间点左侧的数据
FastSort(CurrentRightIndex+1, RightIndex);//排列中间点右侧的数据
}
static void NumInit()
{
RequireSortNum = new double[100];
Random rand = new Random();
for(int a = 0;a < 100;a++)
RequireSortNum[a] = 100 * rand.NextDouble();
}
static void ShowCurrentSort()
{
foreach (double item in RequireSortNum)
Console.WriteLine(item.ToString("f0"));
Console.Write("\n\n\n");
}
}
}