`

快速排序及其简单优化

阅读更多

       快速排序是我们大一进入学校就会的东西,但我发现自己到了大学之后学东西非常 生硬,都是被别人灌输的,缺少了自己思考的过程,这几天被左神一语惊醒,我们学习算法应该是一个思考与探索的过程,不是简单的把这道题AC了就完事了,那我们大学之前那么辛苦可不是为了来大学玩的,所以以后要学会思考和学会探索;

       首先今天我们来讲的是快速排序,这里用三种方法来写快排的;

 ①设定一个标志,两个 哨兵分别从两端开始行走的方法,主代码如下:

public static void quickSort(int[] arr,int l,int r){

        if ( l < r ){
            //随机出标志数
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int q = partition(arr ,l , r);
            quickSort(arr,l,q-1);
            quickSort(arr,q+1,r);
        }
    }

public static int partition(int[] arr,int l,int r){
        int p = arr[l];//设置标志位置
        int i = l;//左哨兵
        int j = r;//右哨兵
        while (i < j){
            while (arr[j] >= p && i < j){
                j--;
            }
            if (i<j){
                swap1(arr,i,j);
            }
            while (arr[i] <= p && i < j){
                i++;
            }
            if (i<j){
                swap1(arr,i,j);
            }
        }
        return i;
    }

 ②把最右边的设置 为标志位,一个哨兵 从最左侧依次进行比较,把 数组 分为两个区,代码 如下:

public static void quickSort2(int[] arr,int l,int r){

        if ( l < r ){
            //随机产生标志位
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int q = partition2(arr,l,r);
            quickSort(arr,l,q-1);
            quickSort(arr,q+1,r);
        }
    }

public static int partition2(int[] arr,int l,int r){
        int i = l-1;
        int j = r;
        while (l < j){
            //每次把最右边的设置为标志位,这样减少了额外空间
            if (arr[l]<=arr[r]){
                i++;
                swap1(arr,i,l);
                l++;
            }else{
                j--;
                swap1(arr,j,l);
            }
        }
        swap1(arr,j,r);
        return i+1;
    }

 ③把数组分为三部分,大于区,小于区和等于区,这样会减少比较的次数,代码如下:

public static void quickSort1(int[] arr,int l,int r){

        if ( l < r ){
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int[] q = partition1(arr,l,r);
            quickSort(arr,l,q[0]-1);
            quickSort(arr,q[0]+1,r);
        }
    }

 //划分数组的优化算法,把一个数组分为三个区,大于区,小于区和等于区
    public static int[] partition1(int[] arr,int l,int  r){
        int i = l-1;
        int j = r;
        while (l < j){
            //每次把最右边的设置为哨兵,这样减少了额外空间
            if (arr[l]<arr[r]){
                swap1(arr,++i,l++);
            }else if (arr[l]>arr[r]){
                swap1(arr,--j,l);
            }else {
                l++;
            }
        }
        swap1(arr,j,r);
        return new int[] {i+1,j};
    }

 完整代码如下:

package study.tao.sort;

import java.util.Arrays;

/**
 * Created by Taoyongpan on 2017/11/13.
 * 快速排序及其优化,我们一般快排的时候会把一个数组 分为两个区
 * 大于等于和小于两个区,现在我们要做的是讲一个数组分为三个区,大于,等于和小于三个区
 * 这样做的好处是每次把相等的数放在中间位置,这样会减少比较次数
 */
public class QuickSort {

    //随机产生一个数组 大小为maxSize,最大值为maxValue的数组
    public static int[] generateRandomArray(int maxSize,int maxValue){
        if (maxSize<=0){
            return null;
        }
        int[] arr = new int[(int)((maxSize+1)*Math.random())];

        for (int i = 0 ; i < arr.length ; i++){
            arr[i] = (int) ((maxValue+1)*Math.random());
        }
        return arr;
    }

    //数组的输出函数
    public static void printArray(int[] arr){
        if (arr==null){
            return;
        }
        for (int j = 0 ; j < arr.length ; j++){
            System.out.print(arr[j]+" ");
        }
        System.out.println();
    }

    //复制函数
    public static int[] copyArray(int[] arr){
        int[] res = new int[arr.length];
        if (arr == null){
            return null;
        }
        for (int i = 0 ; i < arr.length ; i++){
            res[i] = arr[i];
        }
        return res;
    }

    //交换函数
    //位运算进行交换
    public static void swap(int[] arr,int i,int j){
        arr[i] = arr[i]^arr[j];
        arr[j] = arr[i]^arr[j];
        arr[i] = arr[i]^arr[j];
    }
    //需要额外空间的交换函数
    public static void swap1(int[] arr,int i,int j){
        int temp;
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    //系统的比较函数
    public static void arraySort(int[] arr){
        Arrays.sort(arr);
    }

    //比较自己写的排序函数和系统的排序函数结果是否相等
    public static boolean isEqual(int[] arr1,int[] arr2){
        if ((arr1 == null && arr2 !=null)||(arr1 !=null && arr2 ==null)||( arr1 == null && arr2 == null)){
            return false;
        }
        if (arr1.length != arr2.length){
            return false;
        }
        for (int i = 0 ; i <arr1.length;i++){
            if (arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }
    //快速排序
    public static void quickSort(int[] arr,int l,int r){

        if ( l < r ){
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int q = partition(arr ,l , r);
            quickSort(arr,l,q-1);
            quickSort(arr,q+1,r);
        }
    }
    public static void quickSort1(int[] arr,int l,int r){

        if ( l < r ){
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int[] q = partition1(arr,l,r);
            quickSort(arr,l,q[0]-1);
            quickSort(arr,q[0]+1,r);
        }
    }
    public static void quickSort2(int[] arr,int l,int r){

        if ( l < r ){
            swap1(arr, l + (int) (Math.random() * (r - l + 1)), r);
            int q = partition2(arr,l,r);
            quickSort(arr,l,q-1);
            quickSort(arr,q+1,r);
        }
    }
    //定位函数
    //划分数组,用两个哨兵的方法
    public static int partition(int[] arr,int l,int r){
        int p = arr[l];//设置哨兵位置
        int i = l;
        int j = r;
        while (i < j){
            while (arr[j] >= p && i < j){
                j--;
            }
            if (i<j){
                swap1(arr,i,j);
            }
            while (arr[i] <= p && i < j){
                i++;
            }
            if (i<j){
                swap1(arr,i,j);
            }
        }
        return i;
    }
    //划分数组的优化算法,把一个数组分为三个区,大于区,小于区和等于区
    public static int[] partition1(int[] arr,int l,int  r){
        int i = l-1;
        int j = r;
        while (l < j){
            //每次把最右边的设置为哨兵,这样减少了额外空间
            if (arr[l]<arr[r]){
                swap1(arr,++i,l++);
            }else if (arr[l]>arr[r]){
                swap1(arr,--j,l);
            }else {
                l++;
            }
        }
        swap1(arr,j,r);
        return new int[] {i+1,j};
    }
    //划分数组的一级优化
    public static int partition2(int[] arr,int l,int r){
        int i = l-1;
        int j = r;
        while (l < j){
            //每次把最右边的设置为哨兵,这样减少了额外空间
            if (arr[l]<=arr[r]){
                i++;
                swap1(arr,i,l);
                l++;
            }else{
                j--;
                swap1(arr,j,l);
            }
        }
        swap1(arr,j,r);
        return i+1;
    }
    //主函数
    public static void main(String[] args){

        int maxSize = 100;
        int maxValue = 100;
        int maxTime = 3;
        boolean flag = true;
        int[] arr1 = generateRandomArray(maxSize,maxValue);//随机生成数组
        int[] arr2 = copyArray(arr1);//把数组1中的值复制到arr2中

        quickSort(arr1,0,arr1.length-1);
        arraySort(arr2);

        quickSort1(arr1,0,arr1.length-1);
        arraySort(arr2);

        quickSort2(arr1,0,arr1.length-1);
        arraySort(arr2);
        System.out.println(isEqual(arr1,arr2)?"succeed":"failed");
        printArray(arr1);
    }
}

 

分享到:
评论

相关推荐

    PHP排序算法之快速排序(Quick Sort)及其优化算法详解

    快速排序算法由于其实现简单、平均时间复杂度低且速度快,被广泛应用于各种编程语言和实际的软件开发中。在PHP中实现快速排序算法时,需要特别注意数组引用传递和变量的作用域问题,因为在PHP中默认的数组参数传递是...

    快速排序 数据结构 实现

    快速排序是一种高效的排序算法,由英国计算机科学家C.A.R....以上就是关于快速排序的基本原理、实现细节及其测试策略的详细说明。在实际编程中,理解和掌握快速排序的这些知识点对于编写高效的排序代码至关重要。

    普林斯顿快速排序PPT

    快速排序因其高效的性能以及相对简单的实现,在实际应用中被广泛采用。理解其工作原理及其实现细节对于提升算法素养非常有帮助。通过以上介绍,我们不仅了解了快速排序的基本流程,还掌握了其实现方法及应用场景,这...

    数据结构排序里的快速排序

    ### 数据结构排序里的快速排序 ...通过对给定代码的理解和分析,我们可以更深入地理解快速排序的工作原理及其优缺点。通过合理的优化策略,可以进一步提高其效率,使其在实际应用中发挥更大的作用。

    基于Java实现各种基本排序及简单优化

    3. **快速排序的优化**:使用三数取中法选取基准值,避免最坏情况;对于小规模子数组,可改用插入排序。 4. **堆排序的优化**:在构建堆的过程中,可以使用迭代而不是递归,减少函数调用的开销。 在“Java 排序 ...

    C经典算法之快速排序法(二)

    ### C经典算法之快速排序法(二) #### 知识点概述 本篇文章将深入探讨快速排序算法的一个改进版本,并通过具体的代码...通过阅读和理解本文的代码示例,读者可以更好地掌握快速排序算法的核心思想及其实际应用技巧。

    交换类排序(内有经典的冒泡排序和快速排序C++代码实现)

    交换排序是一种基于比较的排序算法,它通过交换...而快速排序在大多数情况下表现出较高的性能,是大规模数据排序的首选,但在最坏情况下需要优化。在实际编程中,根据具体需求和数据特性选择合适的排序算法至关重要。

    六种基本排序算法,堆,归并,希尔,快速排序等

    在计算机科学中,排序算法是数据处理的重要组成部分,它们用于将一组无序的数据按照特定顺序进行排列。...了解这些基础排序算法有助于我们理解更高级的排序算法,如快速排序、归并排序的变体以及各种优化技术。

    快速排序.pdf

    ### 快速排序知识点详解 #### 一、快速排序简介 快速排序是一种高效的排序算法,由C.A.R....它通过对数组进行递归分割来实现排序...通过以上内容的详细介绍,我们可以更深入地理解快速排序算法的工作原理及其应用场景。

    排序算法快速排序(C语言)

    以下是关于快速排序及其C语言实现的详细知识点: 1. **基本概念**: 快速排序是一种比较排序,它通过选取一个基准元素,将待排序数组分为两部分,一部分的所有元素都小于基准,另一部分的所有元素都大于或等于基准...

    数据结构课程设计(快速排序).docx

    通过本次数据结构课程设计,我们深入了解了快速排序算法的设计思想、实现步骤及其性能特点。快速排序作为一种经典的排序算法,在实际应用中非常广泛。通过对算法的不同变体的研究,我们可以进一步提高其性能,以适应...

    NlogN经典排序算法的实现-希尔排序,快速排序,归并排序.zip

    2. **快速排序**:适用于大多数情况,尤其是大数据集,平均性能优秀,但最坏情况需要注意优化,如采用随机化版本避免。 3. **归并排序**:稳定且适用于大规模数据,特别是当内存不是问题时,但需要额外空间,不适合...

    快速和插入排序

    快速排序和插入排序是两种广泛使用的排序算法,它们在计算机科学和编程中有着重要的地位,尤其是在数据处理和算法分析方面。下面将详细讲解这两种排序算法的原理、Java实现及其特点。 **快速排序** 快速排序是一种...

    高维度数据的并行快速排序算法.pptx

    此外,快速排序算法实现简单,不需要额外的存储空间。 - **快速排序的缺点**:快速排序在最坏情况下的时间复杂度为O(n^2),这通常发生在数据已经部分有序的情况下。此外,递归调用可能导致栈溢出的问题。 **1.3 多...

    简单排序

    本文将围绕“简单排序”这一主题,深入探讨几种常见的基础排序算法,包括冒泡排序、插入排序、选择排序以及快速排序等,并结合源码分析其工作原理和性能特点。 一、冒泡排序 冒泡排序是一种直观的排序方法,它通过...

    关系系统及其查询优化

    ### 关系系统及其查询优化 #### 一、关系系统与关系模型 在数据库技术中,**关系系统**是指能够一定程度上支持关系模型的数据库管理系统。关系模型由三个基本部分组成:关系数据结构、关系操作集合以及关系完整性...

    基于matlab实现的matlab 实现快速排序算法 一共有主程序,分类,插入和选择四个程序 .rar

    MATLAB的代码实现通常直观且易读,它提供了丰富的内建函数来支持数组操作,这使得实现快速排序变得相对简单。然而,理解和优化快速排序算法的性能则需要深入理解分治法、递归以及算法效率分析。通过实践和调试这四个...

    随机数排序_20个随机数_数组排序_源码

    例如,简单的排序算法如冒泡排序易于理解和实现,而更高效的算法如快速排序或归并排序则能提供更好的性能。 4. **冒泡排序**:冒泡排序是一种简单的排序算法,通过不断交换相邻的未排序元素来逐步将最大(或最小)...

    各个排序算法及其代码.pdf

    本文档主要介绍了四种常见的排序算法:插入排序、Shell排序、冒泡排序和快速排序,每种算法都有其独特的思想和实现方式。 1. **插入排序**: 插入排序是最基础的排序算法之一,它通过不断将当前元素插入到已排序的...

Global site tag (gtag.js) - Google Analytics