• 算法设计:两种快速排序代码实现


    快速排序是一种高效且使用广泛的排序算法,在很多语言的标准库中自带的排序都是快速排序,所以我们也有必要了解快排的原理以及其实现方法。

    快排的大致思想

    快速排序实现的重点在于数组的拆分,通常我们将数组的第一个元素定义为比较元素,然后将数组中小于比较元素的数放到左边,将大于比较元素的放到右边,

    这样我们就将数组拆分成了左右两部分:小于比较元素的数组;大于比较元素的数组。我们再对这两个数组进行同样的拆分,直到拆分到不能再拆分,数组就自然而然地以升序排列了。

    不难看出,拆分算法是整个快速排序中的核心,快速排序拥有非常多的拆分方式,在本篇文章中我们介绍其中的两种,我个人将它称作:单指针遍历法与双指针遍历法(在下文中用英文单词split和partition称呼)

    split算法解析

    split算法使用一个单向的指针来对数组进行遍历,首先将数组首元素设置为比较元素,然后将第二个开始的元素依次与比较元素比较,如果大于比较元素则跳过,如果小于比较元素,则将其与前面较大的元素进行交换,将数组中所有元素交换完毕后,再将比较元素放到中间位置。

     

    split算法实现(c):

     1 //划分数组的函数
     2 int split(int a[], int low, int high)
     3 {
     4     int i = low;    //i指向比较元素的期望位置
     5     int x = a[i];    //将该数组第一个元素设置为比较元素
     6     //从数组的第二个元素起开始遍历,若找到的元素大于比较元素,则跳过
     7     for(int j = low+1;j<=high;j++)
     8         //若找到了小于比较元素的数,则将其与前面较大的数进行交换
     9         if (a[j] <= x)
    10         {
    11             i++;
    12             swap(a[i], a[j]);
    13         }
    14     swap(a[low], a[i]);    //将比较元素交换到期望位置
    15     return i;
    16 }

    split算法实现(java):

     1 //划分数组
     2     public static int split(int a[], int low, int high)
     3     {
     4         int i = low;    //i指向比较元素的期望位置
     5         int x = a[low];    //将该组的第一个元素作为比较元素
     6         //从第二个元素开始,若当前元素大于比较元素,将其跳过
     7         for(int j = low+1; j <= high; j++)
     8             //若找到了小于比较元素的元素,将其与前面较大的元素进行交换
     9             if(a[j] <= x)
    10             {
    11                 i++;
    12                 if(i != j)
    13                     swap(a, i, j);
    14                 
    15             }
    16         swap(a, i, low);     //将比较元素交换到正确的位置上
    17         return i;    //返回比较元素的位置
    18     }

    partition算法解析

    partition算法使用头尾两个方向相反的指针进行遍历,先将数组第一个元素设置为比较元素,头指针从左至右找到第一个大于比较元素的数,尾指针从右至左找到第一个小于比较元素的数,全部交换完毕后将比较元素放到中间位置。

    partition算法实现(c):

     1 int partition(int a[], int low, int high)
     2 {
     3     int x = a[low];    //将该数组第一个元素设置为比较元素
     4     int i = low;    //指向数组头的指针
     5     int j = high;    //指向数组尾的指针
     6     while (i < j)
     7     {
     8         while (i < j && a[j] >= x)
     9             j--;    //从右至左找到第一个小于比较元素的数
    10         while (i < j && a[i] <= x)
    11             i++;    //从左至右找到第一个大于比较元素的数
    12         /*需要注意的是,这里的j--与i++的顺序不可以调换!
    13           如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头*/
    14 
    15         //将大数与小数交换
    16         if (i != j)
    17             swap(a[i], a[j]);
    18     }
    19     swap(a[low], a[i]);    //将比较元素交换到期望位置
    20     return i;    //返回比较元素的位置
    21 }

    partition算法实现(java):

     1     //划分数组
     2     public static int partition(int a[], int low, int high)
     3     {
     4         int x = a[low];    //将该数组第一个元素设置为比较元素
     5         int i=low;
     6         int j=high;
     7         while(i < j)
     8         {
     9             while(i<j && a[i] <= x)
    10                 i++;
    11             while(i<j && a[j] >= x)
    12                 j--;
    13             
    14             
    15             if(i!=j)
    16                 swap(a, i, j);
    17         }
    18         swap(a, j, low);
    19         return j;
    20     }

    两种算法的完整代码和实际演示

    split算法(c):

     1 #include<stdio.h>
     2 
     3 void swap(int &a, int &b)
     4 {
     5     int t = a;
     6     a = b;
     7     b = t;
     8 }
     9 
    10 //划分数组的函数
    11 int split(int a[], int low, int high)
    12 {
    13     int i = low;    //i指向比较元素的期望位置
    14     int x = a[i];    //将该数组第一个元素设置为比较元素
    15     //从数组的第二个元素起开始遍历,若找到的元素大于比较元素,则跳过
    16     for(int j = low+1;j<=high;j++)
    17         //若找到了小于比较元素的数,则将其与前面较大的数进行交换
    18         if (a[j] <= x)
    19         {
    20             i++;
    21             swap(a[i], a[j]);
    22         }
    23     swap(a[low], a[i]);    //将比较元素交换到期望位置
    24     return i;
    25 }
    26 
    27 //快速排序
    28 void quicksort(int a[], int low, int high)
    29 {
    30     if (low < high)
    31     {
    32         int i = split(a, low, high);    //划分数组并获得比较元素位置
    33         quicksort(a, low, i - 1);    //对比较元素左边进行排序
    34         quicksort(a, i + 1, high);    //对比较元素右边进行排序
    35     }
    36 }
    37 
    38 int main()
    39 {
    40     int a[] = { 5,7,1,6,4,8,3,2 };
    41     int length = sizeof(a) / sizeof(a[0]);
    42     quicksort(a, 0, length - 1);
    43     for (int i = 0; i < length; i++)
    44         printf("%d ", a[i]);
    45     printf("
    ");
    46     return 0;
    47 }

    split算法(java):

     1 //快速排序split实现方法
     2 public class T1 {
     3     public static void main(String args[])
     4     {
     5         int a[] = {5,7,1,6,4,8,3,2};
     6         quickSort(a, 0, a.length-1);
     7         for(int i=0;i<a.length;i++)
     8             System.out.print(a[i] + " ");
     9         System.out.println();
    10     }
    11     
    12     //交换方法
    13     public static void swap(int a[], int i, int j)
    14     {
    15         int t = a[i];
    16         a[i] = a[j];
    17         a[j] = t;
    18     }
    19     
    20     //划分数组
    21     public static int split(int a[], int low, int high)
    22     {
    23         int i = low;    //i指向比较元素的期望位置
    24         int x = a[low];    //将该组的第一个元素作为比较元素
    25         //从第二个元素开始,若当前元素大于比较元素,将其跳过
    26         for(int j = low+1; j <= high; j++)
    27             //若找到了小于比较元素的元素,将其与前面较大的元素进行交换
    28             if(a[j] <= x)
    29             {
    30                 i++;
    31                 if(i != j)
    32                     swap(a, i, j);
    33                 
    34             }
    35         swap(a, i, low);     //将比较元素交换到正确的位置上
    36         return i;    //返回比较元素的位置
    37     }
    38     
    39     public static void quickSort(int a[], int low, int high)
    40     {
    41         if(low < high)
    42         {
    43             int i = split(a, low, high);    //划分并获取比较元素的位置
    44             quickSort(a, low, i-1);     //对比较元素左边的数组进行排序
    45             quickSort(a, i+1, high);     //对比较元素右边的数字进行排序
    46         }
    47     }
    48 }

    partition算法(c):

     1 #include<stdio.h>
     2 
     3 //交换函数
     4 void swap(int &a, int &b)
     5 {
     6     int t = a;
     7     a = b;
     8     b = t;
     9 }
    10 
    11 int partition(int a[], int low, int high)
    12 {
    13     int x = a[low];    //将该数组第一个元素设置为比较元素
    14     int i = low;    //指向数组头的指针
    15     int j = high;    //指向数组尾的指针
    16     while (i < j)
    17     {
    18         while (i < j && a[j] >= x)
    19             j--;    //从右至左找到第一个小于比较元素的数
    20         while (i < j && a[i] <= x)
    21             i++;    //从左至右找到第一个大于比较元素的数
    22         /*需要注意的是,这里的j--与i++的顺序不可以调换!
    23           如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头*/
    24 
    25         //将大数与小数交换
    26         if (i != j)
    27             swap(a[i], a[j]);
    28     }
    29     swap(a[low], a[i]);    //将比较元素交换到期望位置
    30     return i;    //返回比较元素的位置
    31 }
    32 
    33 void quicksort(int a[], int low, int high)
    34 {
    35     if (low < high)
    36     {
    37         int i = partition(a, low, high);    //划分数组并获取比较元素的位置
    38         quicksort(a, low, i - 1);    //对比较元素左边进行排序
    39         quicksort(a, i + 1, high);    //对比较元素右边进行排序
    40     }
    41 }
    42 
    43 int main()
    44 {
    45     int a[] = { 5,7,1,6,4,8,3,2 };
    46     int length = sizeof(a) / sizeof(a[0]);
    47     quicksort(a, 0, length - 1);
    48     for (int i = 0; i < length; i++)
    49         printf("%d ", a[i]);
    50     printf("
    ");
    51     return 0;
    52 }

    partition算法(java):

     1 //快速排序partition实现方法
     2 public class T2 {
     3     public static void main(String args[])
     4     {
     5         int a[] = {5,7,1,6,4,8,3,2};
     6         quicksort(a, 0, a.length-1);
     7         for(int i=0;i<a.length;i++)
     8             System.out.print(a[i] + " ");
     9         System.out.println();
    10     }
    11     
    12     public static void swap(int a[], int i, int j)
    13     {
    14         int t = a[i];
    15         a[i] = a[j];
    16         a[j] = t;
    17     }
    18     
    19     //划分数组
    20     public static int partition(int a[], int low, int high)
    21     {
    22         int x = a[low];    //将该数组第一个元素设置为比较元素
    23         int i=low;
    24         int j=high;
    25         while(i < j)
    26         {
    27             while(i<j && a[j] >= x)
    28                 j--;     //从右至左找到第一个小于比较元素的数
    29             while(i<j && a[i] <= x)
    30                 i++;     //从左至右找到第一个大于比较元素的数
    31             /*需要注意的是,这里的j--与i++的顺序不可以调换!
    32              *如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头*/
    33             
    34             //将大数与小数交换
    35             if(i!=j)
    36                 swap(a, i, j);
    37         }
    38         swap(a, i, low);    //将比较元素交换到期望位置
    39         return i;     //返回比较元素的位置
    40     }
    41     
    42     public static void quicksort(int a[], int low, int high)
    43     {
    44         if(low < high)
    45         {
    46             int i = partition(a, low, high);    //划分数组并获取比较元素的位置
    47             quicksort(a, low, i-1);     //对比较元素左边进行排序
    48             quicksort(a, i+1, high);     //对比较元素右边进行排序
    49         }
    50     }
    51 }

     

  • 相关阅读:
    稳定性「三十六计」- 无状态化
    设置默认的超时和重试是一个基础设施的基本素养
    「前任的50种死法」开发踩坑案例--慢就是错
    稳定性「三十六计」- 配额管控
    编写代码的「八荣八耻」- 以开关上线为荣,以自信编码为耻
    Kubernetes的DaemonSet(下篇)
    使用Elasticsearch的动态索引和索引优化
    Kubernetes的DaemonSet(上篇)
    程序媛的人生观
    Kubernetes的污点和容忍(下篇)
  • 原文地址:https://www.cnblogs.com/sunriseblogs/p/10009890.html
Copyright © 2020-2023  润新知