算法常识——快速排序

Posted aoximin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法常识——快速排序相关的知识,希望对你有一定的参考价值。

前言

什么是快速排序?
首先问道:比如说从大到小,如何确定一个数组中的一个数已经排好了顺序?
这个当然有很多种方式,比如说排序的时候最大值在最左边,那么确定了最左边的位置,这就是冒泡的最基本的原理。
快速排序同样有自己的规则,如果一个数的右边都小于他,左边都大于他,是否这个数不需要变换位置?
答案是,是的。
快速排序就是这个原理,快速排序又分为了:
1.双边循环排序;
2.单边循环排序;
这个下面具体会介绍到。
一些术语:
基准元素:当前需要确定的元素,也就是对比元素。

双边循环排序

参考:程序员小灰这本书
技术图片
比如说我要对4进行排序,那么,我需要做的事比较1,因为1<4,那么继续往后2小与4,然后继续往后,4<6,保留当前6的索引。
然后从右开始,是7,7>4,那么继续往前,然后8也大于,继续,然后是2小于,那么6和2交互位置。然后一直循环下去,当left等于right,那么结束,并且4和left等于right这个位置上交换数字。
下面使用的递归方式,代码也相当简单。

static void Main(string[] args)
{
    int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    quickSort(intarr,0,intarr.Length);
}

public static void quickSort(int []arr,int startIndex,int endIndex)
{
    if (startIndex == endIndex)
    {
        return;
    }
    var baseIndex=changeIndex(arr,startIndex,endIndex);
    quickSort(arr,startIndex,baseIndex-1);
    quickSort(arr, baseIndex+1, endIndex);
}

public static int changeIndex(int []arr,int startIndex,int endIndex)
{
    var baseNum = arr[startIndex];
    // 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    var right = endIndex;
    var left = startIndex;
    while (right != left)
    {
        while (right<left&&arr[left]<= baseNum)
        {
            left++;
        }
        while (right<left&& arr[right] > baseNum)
        {
            right--;
        }
        if (right != left)
        {
            var temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }
    arr[startIndex] = arr[left];
    arr[left] = baseNum;
    return left;
}

单边循环排序

单边循环 如下图:
技术图片

比如说4大于1那么不变,然后4>2同样不变,然后到5,5>4,将这个标记记为mark,就是说这个以后要用一个小的数字来替换,然后4>3,所以用3和5替换掉。
我一开始是有一个疑问的,如果后面继续是比5大的数呢?mark是否要移动过去,其实是不用的,因为这样的用途是把小于4的尽量往左迁移,这才是真正的用途。
代码比较简单如下:

static void Main(string[] args)
{
    int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    quickSortSingle(intarr,0,intarr.Length);
}
public static void quickSortSingle(int[] arr, int startIndex, int endIndex)
{
    if (startIndex >= endIndex)
    {
        return;
    }
    var baseIndex = changeSingleIndex(arr, startIndex, endIndex);
    quickSortSingle(arr, startIndex, baseIndex - 1);
    quickSortSingle(arr, baseIndex + 1, endIndex);
}

public static int changeSingleIndex(int[] arr, int startIndex, int endIndex)
{
    var baseNum = arr[startIndex];
    // 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    var left = startIndex;
    var mark = startIndex;
    var temp = 0;
    for (var i=left+1;i<=endIndex;i++)
    {
        if (baseNum > arr[i])
        {
            mark++;
            temp = arr[mark];
            arr[mark] = arr[i];
            arr[i] = temp;
            left = mark;
        }
    }
    arr[startIndex] = arr[left];
    arr[left] = baseNum;
    return left;
}

不用递归实现

static void Main(string[] args)
{
    int[] intarr = new int[] {1,6,8,2,3,5,10,48,9 };
    quickSortSingle(intarr,0,intarr.Length);
}
public static void quickSortSingle(int[] arr, int startIndex, int endIndex)
{
    Stack stack = new Stack();
    Tuple<int, int> tuple = new Tuple<int, int>(startIndex, endIndex);
    stack.Push(tuple);
        //
    while (stack.Count!=0)
    {
        var oc= (Tuple<int, int>)stack.Pop();
        if (oc.Item1< oc.Item2)
        {
            var baseIndex= changeSingleIndex(arr, oc.Item1, oc.Item2);
            Tuple<int, int> temp = new Tuple<int, int>(startIndex, baseIndex - 1);
            Tuple<int, int> temp2 = new Tuple<int, int>(baseIndex +1 , endIndex);
            stack.Push(temp);
            stack.Push(temp2);
        }
    }
}

public static int changeSingleIndex(int[] arr, int startIndex, int endIndex)
{
    var baseNum = arr[startIndex];
    // 为什么要从新赋值?startIndex 和 endIndex 是范围的意思,left 和 right 是对比变化的意思。
    var left = startIndex;
    var mark = startIndex;
    var temp = 0;
    for (var i=left+1;i<=endIndex;i++)
    {
        if (baseNum > arr[i])
        {
            mark++;
            temp = arr[mark];
            arr[mark] = arr[i];
            arr[i] = temp;
            left = mark;
        }
    }
    arr[startIndex] = arr[left];
    arr[left] = baseNum;
    return left;
}

public static void quickSort(int []arr,int startIndex,int endIndex)
{
    if (startIndex == endIndex)
    {
        return;
    }
    var baseIndex=changeIndex(arr,startIndex,endIndex);
    quickSort(arr,startIndex,baseIndex-1);
    quickSort(arr, baseIndex+1, endIndex);
}

以上是关于算法常识——快速排序的主要内容,如果未能解决你的问题,请参考以下文章

快速排序-递归实现

算法常识——冒泡排序

C1认证学习十四十五(算法常识HTML Head 头)

C1认证学习十四十五(算法常识HTML Head 头)

算法排序之堆排序

一行Python代码搞定快速排序算法