学过的算法中最快捷——快速排序法

前言

       上次总结了其他的三种算法:选择排序、冒泡排序和插入排序,这次总结一个更加高效的排序算法——快速排序法,如果想要了解其余三种算法,请移步c#版选择法、冒泡法、插入法和快速排序法分析与对比


快速排序法

步骤:

  • 1.随便找一个基准数,一般都拿左边第一个数当做基准数
  • 2.给基准数找到一个合适的位置,让其左边的数都小于它,右边的数都大于它
  • 3.这个基准数的位置自然将队列分为了两部分,再对这两部分分别进行步骤一和步骤二,直到排序完成
现在我们来看看如何实现:
  • 首先我们以第一个数为基准,也就是5
  • 定义两个变量i和j,j从右往左找一个比5小的数,找到4停止;i从左向右找一个比5大的数,也就是7停止;
  • 将4和7交换位置
  • 两个变量继续寻找,这里需要强调一点,一定是让j先从右边开始找,这个之后再做解释
  • 这是j找到了1,而i与j相遇了,代表探测结束,这时让基准数与1进行位置交换,通过第一次的探测,我们已经找到了基准数在队列中的位置,这时的队列为1,4,0,3,5,7,9,6,,可以发现,5对左边都是比他小的数,而右边都是比他大的数
  • 队列以“5”为分界点,分成了两部分,我们在分别对这两部分应用之前的步骤,知道队列排序完成



为什么一定要J先找?
我们看下边这种情况,如果i先找,那么i和j将会在“7”相遇,这时将二者交换,那么5的左边就不是都比他小的数了




之后左边再次执行之前的步骤:(右边同理)
画下划线的数字是基准数,红色的是分界点




注意:
       队列不断的被归为的基准数分为两部分的时候,左右两部分通过递归调用来完成排序,也就是说不断的调用自己来完成排序


代码

<strong style="font-size:24px;"> </strong><span style="font-size:14px;">/// <summary>
        /// 快速排序法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //哈希表转整数数组
            int[] s = hs.ToArray();
            DateTime time1 = DateTime.Now;

            int low=0;                 //记录目标数组的起始位置
            int high=s.Length-1;   //记录目标数组的结束位置

            QuickSortFunction(s, low, high);

            DateTime time2 = DateTime.Now;
            textBox4.Text = DateDiff(time1, time2);

            for (int i = listBox1.Items.Count - 1; i >= 0; i--)
            {
                listBox1.Items.RemoveAt(i);
            }
            for (int i = 0; i < s.Length; i++)
            {

                this.listBox1.Items.Add(s[i]);
            }
        }


         /// <summary>
         /// 快速排序过程
         /// </summary>
         /// <param name="array">数组</param>
         /// <param name="low">低位目标数组下标</param>
         /// <param name="high">高位目标数组下边</param>
        private static void QuickSortFunction(int[] array, int low, int high)
         {
                 int keyValuePosition;   //记录关键值的下标
 
                 //当传递的目标数组含有两个以上的元素时,进行递归调用。(即:当传递的目标数组只含有一个元素时,此趟排序结束)
                 if (low < high) 
                 {
                     keyValuePosition = keyValuePositionFunction(array, low, high);  //获取关键值的下标(快排的核心)
 
                     QuickSortFunction(array, low, keyValuePosition - 1);    //递归调用,快排划分出来的左区间
                     QuickSortFunction(array, keyValuePosition + 1, high);   //递归调用,快排划分出来的右区间
                 }
         }

        /// <summary>
        /// 找出关键值位置
        /// </summary>
        /// <param name="array">数组</param>
        /// <param name="low">低位下标</param>
        /// <param name="high">高位下标</param>
        /// <returns>关键值下标</returns>
        private static int keyValuePositionFunction(int[] array, int low, int high)
         {
             int i = low;        //记录目标数组的起始位置(后续动态的左侧下标)
             int j = high;      //记录目标数组的结束位置(后续动态的右侧下标)
 
             int keyValue = array[low];  //数组的第一个元素作为关键值
             int temp;
 
             //当 (左侧动态下标 == 右侧动态下标) 时跳出循环
             while (i< j)
             {
                 while (i < j && array[j] > keyValue)  //必须先从右边开始,逐渐向左移动,直至找到<=keyValue的下标
                 {
                     j--;
                 }
                 while (i < j && array[j] <= keyValue)  //从左边开始,直至找到>=keyValue的下标
                 {
                     i++;
                 }
                 if(i < j)  //如果leftIndex < rightIndex,则交换左右动态下标所指定的值;当leftIndex==rightIndex时,跳出整个循环
                 {
                     temp = array[i];
                     array[i] = array[j];
                     array[j] = temp;
                 }
             }
 
             //当左右两个动态下标相等时(即:左右下标指向同一个位置),此时便可以确定keyValue的准确位置
             temp = keyValue;
             if (temp < array[j])   //当keyValue < 左右下标同时指向的值,将keyValue与rightIndex - 1指向的值交换,并返回rightIndex - 1
             {
                 array[low] = array[j - 1];
                 array[j - 1] = temp;
                 return j - 1;
             }
             else //当keyValue >= 左右下标同时指向的值,将keyValue与rightIndex指向的值交换,并返回rightIndex
             {
                 array[low] = array[j];
                 array[j] = temp;
                 return j;
             }
         }
    </span>


总结:

      之所以快速排序法比较高效是因为他交换的位置不是相邻的交换,而是跨度更宽的位置的交换,这样可以更加精准的确定数的位置,算法很有意思,希望可以学习更多的内容



  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 53
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 53
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值