算法旅行之快速排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Aran_WDX/article/details/81746419

  今天大家一起讨论了交换排序中冒泡排序和快速排序,至于冒泡排序还是很容易理解的,大家也都很开心,不过在讨论快速排序的时候,好像大家都蒙在鼓里,总是觉得有一层隔膜没有突破,堵得难受。因此,经过我和我的算法小伙伴,在纸上讨论完算法的具体过程之后,我们又在代码里经过实现和逐步调试,看明白了值是如何改变的,下面就和大家一起分享一下,如果有什么问题大家可以联系我一起讨论。

  我的博客都想异于常人,那么今天的分享也是不同以往,和别人的不一样。首先我来分想一下我的抽象理解,最后再将逐步截图加上解说送给大家。

快速算法之我的抽象理解:

  我们知道快速算法的过程是需要假设一个轴值,通过左右摇摆确定轴值的位置,把要比较的东西分为两部分,所谓分而治之,也就是这个意思。我们有这样一个数组数组里面的值代表的是每一块金子的重量,而且每一个金子都在一个盒子里面。

下标

0

1

2

3

4

5

6

45

35

66

90

88

10

25

   这时候来了一个小偷Mid,这个小偷头脑还不错,但是却很贪婪,他走到数组的第一个位置也就是下标为0的位置,背着45kg的金子想要跑路。突然发现这个数组仓库有比自己拿的金子还大的金子,他在想我如何才能把我认为比较大的金子一次性都带走呢?

都知道小偷有个癖好,好牛不吃回头草。(永远不再看自己走过的地方)

    于是这个小偷Mid花了两个圈,就把下标大的和小的分开吧,于是Mid把数组仓库分成了两部分,一个叫做low一个叫做hight,小偷Mid背着45kg的金子跑到最后面的位置(6)发现有一个25kg的金子,一愣神,把25扔进了low[0],紧接着Mid又跑到了low[1]的位置,发现35,觉得不如自己背上的大,算了就不扔你了,挺累的。既然没有消耗体力,那就继续沿着low++走,走到low[2]发现,我的天66kg,真大,把66扔进进hight[6](由于hight[6]中原有的25被扔进了low[0],所以按照逻辑它为空)。

   紧接着它又跑到了hight[5]的位置发现10,我凑这忒小啊,把10扔进了low[2]的空盒子。然后Mid看到low[3]中有一90kg,我的天啊,Mid跑到90将它扔进了hight[5]的空盒子。向反方向找,发现4金子也挺大,在一愣神,发现4以后的都挺大,心想我怎么这么棒棒,休息一会,将自己的45kg放进low[3]空盒子里。

    由此一来快速排序的第一轮排序依然完毕,但是大家会有一些疑问,说人是自由的,可以随便跑,随便看,随便把金子扔出去,(还会有人问,那小偷不是傻吗,左看右看,左跑右跑,这个问题将在我们的下一分享中为大家解说)。但是到计算机中,计算机是有执行次序的而且有覆盖的意外,在计算机中怎么运行的呢?

下面我们就将我和我的小伙伴一步一步调试的过程详细解说给大家,仅供参考。

首先这是我们的快速排序代码。//代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 快速排序
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] R = new int[] { 45, 35, 66, 90, 88, 10, 25 };
            QuickSort(R, 0, R.Length - 1);

            foreach (var mid in R)
            {
                Console.WriteLine(mid + " ");
            }
            Console.ReadKey();
        }


        static void QuickSort(int[] R, int low, int hight)//自定义的快速算法
        {
            if (low < hight)
            {
                int index = QucikSortUnit(R, low, hight);
                QuickSort(R, low, index - 1);
                QuickSort(R, index + 1, hight);
            }

        }

        static int QucikSortUnit(int[] R, int low, int hight)
        {
            int mid = R[low];//设置嘉定中间值
            while (low < hight)
            {

                while ((low < hight) && mid < R[hight])
                {
                    hight--;

                }
                R[low] = R[hight];
                while ((low < hight) && mid > R[low])
                {
                    low++;

                }
                R[hight] = R[low];
            }

            R[low] = mid;
            return low;
        }
    }
}

下面我们来走一走程序,一步一步进行。

首先我们走到第一步的算法执行,我们来看执行到下图所视情况的意思就是我们官方语言,假定了第一个数为轴值。可以看到下面的执行结果。

好,我们继续往下走,经过上面的判断,发现我们的mid>R[hight(6)],执行键值覆盖,结果变为如下所示,不难看出,执行完毕以后我们的Mid=45,R[low(0)]变成了R[hight]的值(可以说被覆盖)通过数组值和执行结果对比。

好的,我们明白了,继续往下走,走到下图所示,发现符合条件low++,

这时我们的low得值由0变成了1,继续执行,发现mid大于35,继续low++;

此时low为2,发现mid<low[2]对应的值

执行覆盖(此时的R[hight(6)]得值为25)

此时的值变为:(对比两张图可以理解刚才发生了什么)

紧接着代码跳回,判断此代码的执行结果如下图

继续判断mid<>R[hight(5)],执行

此时大家应该都看明白发生了一些什么事情,这一轮排序完,只是确定了轴值,以及左右两个数,下一次执行,左右两个一起执行重复刚才的类似过程,重复过程就不再过多讲解。

希望大家通过本次分享,能够对快速排序有一个深刻的理解,了解它的执行过程是覆盖而不再是交换。下一篇交换排序会给大家讲解冒泡排序和快速排序的对比,以及上面小编留下的小小疑问。

猜你喜欢

转载自blog.csdn.net/Aran_WDX/article/details/81746419