分而治之之快速排序算法

转载 2018年04月17日 10:03:19

分而治之

概述

分而治之策略不仅被君主和殖民者成功地用来统治殖民地,也可以用来设计有效的计算机算法。它可以用来解决以下问题:最小最大问题、矩阵乘法、一个娱乐数学————残缺棋盘问题、排序、选择和一个计算几何问题————在二维空间中寻找距离最近的点。
分而治之算法把一个问题实例分解为若干个小型而独立的实例,从而可以再并行计算机上执行;那些小而独立的实例,从而可以在并行计算机的不同处理器上完成。

算法思想

分而治之方法与软件设计的模块化非常相似。一个问题的小实例可以直接用方法求解。而要解决一个问题的大实例,可以:
1)把它分解为两个或者多个更小的实例;
2)分别解决每个小实例;
3)把这些小实例的解组合成原始大实例的解。小实例通常是原问题的实例,可以使用分而治之策略递归求解。

应用

快速排序

排序方法

用分而治之的方法可以实现快速排序。 把n个元素划分为3段:左段left、中间段middle和右段right。中段仅有一个元素,左段的元素都不大于中间段的元素,右段的元素都不小于中间段的元素。因此可以对left和right独立排序,并且排序后不用归并。middle的元素称为支点(pivot)或分割元素(partitioning element)。 以下是快速排序的简单描述:

    //对a[0:n-1]快速排序a[0:n-1]中选择一个元素作为支点,组成中间段。
    把剩余元素分为左段left和右段right。使左段的元素关键字都不大于支点关键字,右端的元素关键字都不小于支点的关键字
    对左端递归快速排序
    对右端递归快速排序
    最终结果按照左端、中间段和右段排列

考虑元素序列[4,8,3,7,1,5,6,2]。假设选择元素6作为支点。因此6属于middle;4,3,1,5,2属于left;8和7属于right。left排序的结果为 :1,2,3,4,5;right排序结果为7,8。把右段right的元素放在支点之后,左段left的元素放在支点之前,即可得到有序序列[1,2,3,4,5,6,7,8]。在对数据段[4,3,1,5,2]递归快速排序时,如果选择3为支点,则左段包含1和2,右段包含4和5。左段和右段分别排序后,和支点组成有序段[1,2,3,4,5]。

C++实现

递归快速排序的驱动程序:

        template<class T>
        void quickSort(T a[],int n)
        {
          if(n<1) return 0;
          int max=indexOfmax(a,n);
          swap(a[n-1],a[max]);
          quickSort(a,0,n-2); 
        }

上述排序实现了,将数组a的最大值移动到数组的最右端,之后调用递归函数quickSort函数,该函数的实现如下:

        template<class T>
        void quickSort(T a[],int leftEnd,int rightEnd)
        {
          if(leftEnd>rightEnd)
                 return 0;
          int leftCursor=leftEnd;//从左到右移动的索引
          int rightCursor=rightEnd+1;//从右到左移动的索引
          T pivot=a[leftEnd];

          while(true)
          {
             //寻找左侧不小于支点的元素
             do
             {
               leftCursor++;
             }while(a[leftCurSor]<pivot);
             //寻找右侧不大于支点的元素
             do
             {
               rightCursor--;
             }while(a[rightCurSor]>pivot);
             if(leftCursor>=rightCursor) break;
             swap(a[leftCursor],a[rightCursor]);
          }

          a[leftEnd]=a[rightCursor];
          a[rightCursor]=pivot;

          quickSort(a,leftEnd,rightCursor-1);//对左侧排序
          quickSort(a,rightCursor+1,rightEnd);  //对右侧排序
        }

复杂度分析

以上程序所需要的递归栈空间为O(n)。若使用栈来模拟递归,则需要的空间可以减少为O(log n)。在模拟过程中,首先对数据段left和right中较小的进行排序,把较大者的边界放入栈中。
在最坏的情况下,例如数据段left总是空,这时快速排序用时为O(n^2)。
在最好的情况下,即数据段left和right的元素数目总是大致相同,这时的快速排序用时为O(nlog n).
而快速排序的平均复杂度也是O(nlog n)。

(本文摘自数据结构、算法与应用 第二版)

数据结构JAVA版2017教学视频课程

-
  • 1970年01月01日 08:00

【数据结构笔记】7:非递归快速排序

快速排序,分而治之。在同为O(N*logN)的几种排序方法中效率较高。
  • SHU15121856
  • SHU15121856
  • 2017-05-25 00:39:15
  • 397

“快速排序算法”问题的分而治之算法

/* 标题:>应试编程实例-[分治法程序设计] 作者:成晓旭 时间:2002年09月18日(21:43:00-22:03:00) 实现“快速排序算法”问题的...
  • CXXSoft
  • CXXSoft
  • 2006-07-18 13:54:00
  • 2459

“快速排序算法”问题的分而治之算法

2006年07月18日 13:54:00 /**//* 标题:>>系统设计师 作者:成晓旭 时间:2002年09月18日(21:43:00-22:03:00) ...
  • softart
  • softart
  • 2007-10-29 10:20:00
  • 435

算法--分而治之法

//.5.利用分而治之算法求一个整数数组中的最大值 #if 0 int Max(int a[],int n) { int max1; if(n==1) return a[0]; else { ...
  • liyf__88
  • liyf__88
  • 2017-05-21 17:41:51
  • 377

[算法学习笔记]分而治之——归并排序

归并排序递归的概念递归的概念简单来说就是自己定义自己,来举一个简单的栗子: GNU是GNU is Not UNIX的缩写, 那么其中的GNU还是还是GNU is Not UNIX,即”GNU is ...
  • u014235934
  • u014235934
  • 2016-07-21 20:41:15
  • 975

算法中的分而治之思想

 任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题规模越小,解题所需的计算时间往往也越少,从而也越容易计算。想解决一个较大的问题,有时是相当困难的。分治法的思想就是,将一个难以直接解决...
  • lanhuahua
  • lanhuahua
  • 2007-07-19 20:41:00
  • 3115

分而治之的思想--最大子列和问题

问题描述:给定N个整数序列,{A1,A2,…,An},求该序列中存在的最大的连续n个整数和。...
  • Katherineljn
  • Katherineljn
  • 2017-03-08 14:24:11
  • 888

快速排序(分而治之策略及C语言实现)

提出的问题分而治之的策略 重要的分而治之算法快速排序 问题要在一个长为x,宽为y的长方形中画出均匀且大小相等的正方形 那么正方形的边长为多少 (1)可以看出正方形的边长需要是x和y的最大公约数...
  • superce
  • superce
  • 2017-09-12 20:49:42
  • 407

L2-025.分而治之

分而治之,各个击破是兵家常用的策略之一。在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可行性...
  • qq_41643650
  • qq_41643650
  • 2018-03-31 21:58:52
  • 135
收藏助手
不良信息举报
您举报文章:分而治之之快速排序算法
举报原因:
原因补充:

(最多只允许输入30个字)