• 快速排序


    终于有时间坐下来写一写这半年学习的算法,否则又要白学了。

    1.Partition函数:

        快排中最重要的是划分算法Partition(A,l,r):该算法输入是数组A,以及我们在这次划分中考虑的元素的范围——从下标为l的元素考虑到下标为r的元素。假设总是选取下标为r的元素作为轴p,那么一次划分结束后,p元素左边的元素都比它小,右边的元素都比它大。例如:有数组2 3 1 3 4 2 ,选取末尾红色的2为轴,经过一次划分后数组变为2 1 2 3 4 3,可以看到划分后轴元素2的左边都是小于等于2的元素,右边都是大于2的元素。

        记住算法中重要的变量就可以快速的写出算法,划分函数中主要有三个:i,j,p;p就是上述说的轴元素,假设每次都选取数组最后一个元素作为轴。在划分过程中j是游标,从l遍历到r;i指向比轴p大的元素中最左边的那个,如果发现j指向的元素比轴p小了,就和i指向的元素互换,i向后移动。见下图,红色的2是选中的轴元素,i指向的3是比2大的第一个元素,当前j遍历的元素是1,比轴元素2小,所以将这个1与i指向的元素3交换,得到右边交换后的图。所以这里,我们可以这样理解i,它维护了一个大于p和小于等于p的元素的分界线,并且它指向的元素总是大于p并且“准备”与比p小(或者等于p)的元素交换的。

    2.quick_sort函数

        有了partition函数,快排就很容易写出来了,就是三个步骤:调用partition,递归快排轴左边的元素序列,递归调用轴右边的元素序列。代码如下:

       

     1 #include <iostream>
     2 using namespace std;
     3 int A[10] = {2,5,4,2,1,4,7,8,4,3};
     4 
     5 void Swap(int A[10],int i,int j)
     6 {
     7     int temp = A[i];
     8     A[i] = A[j];
     9     A[j] = temp;
    10 }
    11 int Partition(int A[10],int l,int r)
    12 {
    13     int p = A[r]; //选取最后一个元素最为轴元素
    14     int i = l;
    15     for(int j = l;j <= r-1;j++)
    16     {
    17         if(A[j] <= p)    
    18         {
    19             Swap(A,i,j);   //如果j指向的元素比轴p小,就和i指向的元素互换位置
    20             i++;
    21         }
    22     }
    23     Swap(A,i,r);    //每一次partition的过程中,轴元素p都被放到最终的位置上
    24     return i;
    25 }
    26 
    27 void quick_sort(int A[10],int l,int r)
    28 {
    29     if(l < r){
    30         int pivot = Partition(A,l,r);
    31         quick_sort(A,l,pivot-1);
    32         quick_sort(A,pivot+1,r);
    33     }
    34     return;
    35 }
    36 int main()
    37 {
    38     quick_sort(A,0,9);
    39     for(int i = 0;i <= 9;i++)
    40         cout << A[i]<<" ";
    41     cout <<endl;
    42 }

        说一下partition这个函数,除了在快排中,还有很多其他情况都可以应用。比如《算法导论》Problems8-4的“水壶问题”:有一堆红色水壶和蓝色水壶,所有的红色水壶中水量不等,所有的蓝色水壶中水量不等。对于任意一个红色水壶,对应一个蓝色水壶水量和它相等,比较一个蓝色水壶和红色水壶中水量多少记为一次操作,同色水壶间不能进行水量比较。问多少进行多少次操作,能够把所有红色水壶和蓝色水壶配对。

        这个问题就可以用partition的思想:任意选取一个红色水壶,把它和所有的蓝色水壶比较一遍水量,比它少的放一堆,多的放一堆,相等的单独拿出来,再用这个和它水量相等的蓝色水壶和所有的红色水壶比较一遍,同样分成比它小的和比它大的,这样所有的水壶就被分成三堆,其中一堆为一对已经配对的水壶,对剩下两堆水壶进行递归操作,直到所有水壶都配对。

        最后记一下快排的性质:最优时间复杂度O(nlogn),最坏时间复杂度O(n^2),不稳定排序。之所以速度快是因为它的过程符合现代计算机的cache机制,即每次需要操作的元素在计算机中物理位置很近,通常可以一次性取进cache。

  • 相关阅读:
    列表方块与格式与布局
    框架与样式表的基本概念
    表单
    内容容器,常用标签
    CSS3
    表单验证
    练习题
    document对象
    windows对象
    函数
  • 原文地址:https://www.cnblogs.com/sunshineatnoon/p/3529896.html
Copyright © 2020-2023  润新知