| 加入收藏| 设为首页| 联系我们

首页 站长学习 站长之家 源码下载 建站素材 书籍教程 常用工具
 您现在的位置: 动力中国 >> 网络编程 >> ASP.NET教程 >> 文章正文  
 [组图]递归算法学习系列之三(快速排序)
 

递归算法学习系列之三(快速排序)

http://www.domcn.org  文章来源:本站收藏  点击数:

  关键字:递归算法学习系列之三(快速排序)

        上一篇学习中介绍了了递归算法在排序中的一个应用:归并排序,在排序算法中还有一种算法用到了递归,那就是快速排序,快速排序也是一种利用了分而治之策略的算法,它由C.A.R发明,它依据中心元素的值,利用一系列递归调用将数据表划分成越来越小的子表。在每一步调用中,经过多次的交换,最终为中心元素找到最终的位置。与归并算法不同,快速排序是就地排序,而归并排序需要把元素在临时向量中拷贝,下面通过对以下向量进行排序来理解和加深快速排序算法的步骤:

 v={800,150,300,650,550,500,400,350,450,400};

利用快速排序算法对此数据表进行排序的第0级划分过程如下: 向量v的索引范围为:[first,last) = [0,10),则中心点的索引为mid = (0+10)/2=5,中心点的值为v[5] = 500

快速排序算法的第一次划分的目的就是将向量v依据v[5]的值划分成两个子表subList1和subList2,其中subList1中的值都小于v[5],而subList2中的值都大于v[5],我们将subList1称为左子表,subList2称为右子表,并且确定v[5]的最终位置:下面就是实现这一目的需要我们作出的工作步骤:

1)首先将中心元素与起始位置的元素进行交换。

2)分别扫描左子表和右子表,左子表扫描起始位置为 first+1, 右子表从last-1开始。左子表从左向右扫描扫描,右子表从右向左扫描。直到左子表扫描位置大于或者等于右子表扫描位置时候结束。

在第一个步骤中,得到如下的数据表

500  150  300 650 550 800 400 350 450 400  image ,而此时的左子表扫描位置处于索引1处,右子表扫描位置处于索引9处,先从左子表扫描,直到找到数据值大于中间值500的位置停止扫描,然后扫描右子表,直到找到数据值小于中间值500并且右子表的扫描位置(scanDown)要小于左子表开始位置,防止数据溢出。找到之后,交换左子表与右子表中中扫描位置的元素,图示如下:image ,在交换v[3](650>500)与v[8](450<500)后,继续扫描左子表和右子表,如图(image )直到满足条件scanUp>=scanDown,然后scanDown所在位置就是中心元素500的最终位置,交换v[0]与v[scanDown)=v[5],第一次划分级别的最终结果数据集为:400,150,300,450,350,500,800,550,650,900,此时得到的左子表为:400,150,300,450,350,右子表为:800,550,650,900

下一个划分级别是处理上一级别产生的子表,按照相同的处理方法分别处理左子表和右子表,左子表索引位置[0,5),右子表索引位置[6,10),按照上面的处理步骤处理左子表(400,150,300,450,350)得到的最终结果为:150,300,400,450,350 右子表最终处理结果为:550,650,800,900 在处理结果中300与650分别是中心值,他们现在的位置就是最终位置

在接下来的处理中,总是处理上一步骤中留下的子表,当子表数目<=1的时候就不用处理子表了,而子表有两个元素的时候,比较大小,然后交换两元素位置即可。

大于2个元素的子表都和上面的处理步骤一样,我们将上面的处理过程编写出一个函数

private int PivotIndex(int[] v, int first, int last),那么快速排序算法就是对此函数的递归调用

 

 /**//// <summary>
       /// 交换位置
       /// </summary>
       /// <param name=v></param>
       /// <param name=index1></param>
       /// <param name=index2></param>
       private void Swrap(int[] v, int index1, int index2)
       {
           int temp = v[index1];
           v[index1] = v[index2];
           v[index2] = temp;
       }
       /**//// <summary>
       /// 将向量V中索引{first,last)划分成两个左子表和右子表
       /// </summary>
       /// <param name=v>向量V</param>
       /// <param name=first>开始位置</param>
       /// <param name=last>结束位置</param>
       private int PivotIndex(int[] v, int first, int last)
       {
           if (last == first)
           {
               return last;
           }
           if (last - first == 1)
           {
               return first;
           }
           int mid = (first + last) / 2;
           int midVal = v[mid];
           //交换v[first]和v[mid]
           Swrap(v, first, mid);
           int scanA = first + 1;
           int scanB = last - 1;
           for (; ; )
           

               while (scanA <= scanB && v[scanA] < midVal)
               {
                   scanA++;
               }
               while (scanB > first && midVal <= v[scanB])
               {
                   scanB--;
               }
               if (scanA >= scanB)
               {
                   break;
               }
               Swrap(v, scanA, scanB);
               scanA++;
               scanB--;
           }
           Swrap(v, first, scanB);
           return scanB; 

       }
       public void Sort(int[] v, int first, int last)
       {
           if (last - first <= 1)
           {
               return;
           }
           if (last - first == 2)
           {
               //有两个元素的子表
               if (v[first] > v[last - 1])
               {
                   Swrap(v, first, last - 1);
               }
               return;
           }
           else
           {
               int pivotIndex = PivotIndex(v, first, last);
               Sort(v, first, pivotIndex);
               Sort(v, pivotIndex + 1, last);
           }
       } 


      快速排序因为每次划分都能将中心值元素找到最终的位置,并且左边值都小于中心值,右边都大于中心值,它的时间复杂度平均和归并算法一致为O(nlog2n);

任何一种基于比较的排序算法的时间复杂度不可能小于这个数,除非不使用比较的方法进行排序。


递归算法学习系列之三(快速排序)
  • 上一篇文章:

  • 下一篇文章:
  •  热门文章
    普通文章 电子邮件改头换面 四公司畅谈未
    普通文章 PC病毒史上最声名狼藉的八大病
    普通文章 Rails系统中的AJAX开发技术简析
    普通文章 基于ASP.NET AJAX框架实现表单
    普通文章 开发ASP.NET AJAX客户端定制行
    普通文章 用JFreeChart对JSP报表进行增强
    普通文章 SQL Server 2005上的CLR和ADO.
    普通文章 SQL Server 2005的XML支持机制
    普通文章 Firefox中标签式浏览技巧大全
    普通文章 Tomcat中的Session和Cookie大揭
     
     推荐文章
    推荐文章 把Google地图嵌入网页 就是这么
    推荐文章 迅雷搜索候选资源出错的解决
    推荐文章 轻松去除迅雷里的各种广告和资
    推荐文章 突破限制 免费领养到QQ空间五级
    推荐文章 Rational统一过程RUP贴近中小软
    推荐文章 构建自己的轻量级XML DOM分析程
    推荐文章 WPS Office 2007技巧:妙用配置
    推荐文章 Excel 2007:求余数函数实用进阶
    推荐文章 浅谈ASP.NET的Postback
    推荐文章 软件开发中项目需求管理简述
     
     相关文章
    没有相关文章
    设为首页 | 加入收藏 | 广告合作 | 联系站长 | 版权申明 |
    动力中国为网友提供免费学习资料,可用资源,如果您认为我们的相关内容侵害到了您的权利请联系管理员
    Copyright © 2006-2008 domcn.org All Rights Reserved.