码迷,mamicode.com
首页 > 编程语言 > 详细

算法常识——快速排序

时间:2020-02-03 14:08:54      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:交换   前言   基本   sha   oid   com   循环   pop   图片   

前言

什么是快速排序?
首先问道:比如说从大到小,如何确定一个数组中的一个数已经排好了顺序?
这个当然有很多种方式,比如说排序的时候最大值在最左边,那么确定了最左边的位置,这就是冒泡的最基本的原理。
快速排序同样有自己的规则,如果一个数的右边都小于他,左边都大于他,是否这个数不需要变换位置?
答案是,是的。
快速排序就是这个原理,快速排序又分为了:
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);
}

算法常识——快速排序

标签:交换   前言   基本   sha   oid   com   循环   pop   图片   

原文地址:https://www.cnblogs.com/aoximin/p/12255264.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!