快速排序算法和JAVA实现

快速排序

排序思想:通过一趟排序,将倒排序的序列分成两部分,其中一部分均比另一部门小,然后再对这两部分进行下一趟排序,以达到整个序列有序

平均时间复杂度: O(nlog2(n)),n*log以2为底的n

最坏情况下是:O(n^2) ,n的平方

排序流程

  1. 首先设定一个分界值,通过该分界值将数组分成左右两部分
  2. 大于或等于分界值的数据集中到数组右边小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值(具体看怎么分)
  3. 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
  4. 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了

排序步骤

  1. 设置两个变量i、j,排序开始的时候:i=0,j=N-1
  2. 以第一个数组元素作为关键数据,赋值给key,即key=A[0]
  3. 从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]的值交换
  4. 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换
  5. 重复第3、4步,直到i==j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)

一趟快速排序算法演示

​ 初始关键字序列:49、38、65、97、76、13、27、49

​ 取数组第一位为快排的参照:49

  1. 第一次排序:49跟边49比较,49=49,然后找49>27,将27放到49左边(交换位置)
    • 27、38、65、97、76、13、49、49
  2. 第二次排序:从边找到65>49,交换位置
    • 27、38、49、97、76、13、65、49
  3. 第三次排序:从开始找打13<49,交换位置
    • 27、38、13、97、76、49、65、49
  4. 第四次排序:从找到97>49,交换位置
    • 27、38、13、49、76、97、65、49
  5. 最后一趟排序:从找76,然后找49,下标一致,第一趟结束,继续排序分别排左边和右边数组
    • {27、38、13}、49、{76、97、65、49}

JAVA实现快速排序算法

按快速排序定义实现

public static void main(String[] args) {
    
    
    int[] array = {
    
    49,38,65,97,76,13,27,49};
    int low = 0;
    int high = array.length - 1;
    quicksort(array, low, high);
}

/**
 * 快速排序 ,循环执行 step1 和 step2
 * @param array 数组
 * @param low 每次比较的最低位
 * @param high 每次比较的最高位
 */
private static void quicksort(int[] array,int low,int high) {
    
    
    //记录开始位置,是下次左边数组(比分解值小的一边)排序的最低位。
    int start = low;
    //记录此次排序的最高位,是下次右边数组(比分界值大的一边)排序的最高位
    int end = high;
    //取数组第一位作为分界值
    int ref = array[low];
    //如果低位和高位重合则结束此趟排序
    while (low != high){
    
    
        //step1 先顺高位寻找小于分界值
        while (high > low){
    
    
            //如果array[high] 小于 分界,交换位置 high不指向下一位
            if(array[high] < ref){
    
    
                int temp = array[high];
                array[high] = array[low];
                array[low] = temp;
                printArray(array);
                break;
            }
            high --;
        }
        //step2 低位寻找高于分界值
        while (low < high){
    
    
            //如果array[low]或等于分界值 交换位置,low不指向下一个位置,继续比较高位
            if(array[low] >= ref){
    
    
                int temp = array[high];
                array[high] = array[low];
                array[low] = temp;
                printArray(array);
                break;
            }
            low ++;
        }
    }
    // low的值和最开始进来的值相等,说明只有一位结束循环
   if(low != start){
    
    
        quicksort(array,start,low - 1);
    }
    // low - 1 和 high + 1。因为分解值必然比右边小,必然比左边大,所有一个位置减1一个加1
    if(high != end){
    
    
        quicksort(array,high + 1,end);
    }
}

/**
 * 输出数组内容
 */
private static void printArray(int[] array){
    
    
    Arrays.stream(array).forEach(value -> {
    
    
        System.out.print(value + " ");
    });
    System.out.println();
}

另一种实现百度百科上的

public static void main(String[] args) {
    
    
    int[] array = {
    
    49,38,65,97,76,13,27,49};
    int len = array.length-1;
    qsort(array,0,len);

}

/**
 * 递归调用,第二次用的子数组,注意子数组下标位置
 * @param arr
 * @param start
 * @param end
 */
private static void qsort(int[] arr,int start,int end) {
    
    
    //开始位置的值,标记值 ,大的放右边,小的放左边
    int pivot = arr[start];
    //初始的开始和结束位置赋值给i和j,变动i和j,初始值不变下次递归判断用。
    int i = start;
    int j = end;
    //i < j
    while (i < j) {
    
    
        //当arr[j]最高位大于标记值,则继续寻找下一位,直到找到小于或等于标记值的元素,不超过最低位 i
        while ( i < j && arr[j] > pivot) {
    
    
            j--;
        }
        //arr[i]小于标记值,一直向上寻找,直到找到大于标记值或者找到最高位j结束循环
        while ( i < j && arr[i] < pivot) {
    
    
            i++;
        }
        //如果 arr[i]==arr[j] 则i进一位,且i不能超过j,也就是查找j找过的元素
        if (arr[i]==arr[j] && i < j ) {
    
    
            i++;
        } else {
    
    
            //交换j找到的小于标记值的元素 和 i找到大于标记值的元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            printArray(arr);
        }
    }
    //递归调用
    if (i-1>start) {
    
    
        qsort(arr,start,i-1);
    }
    if (j+1<end) {
    
    
        qsort(arr,j+1,end);
    }
}

/**
 * 输出数组内容
 */
private static void printArray(int[] array){
    
    
    Arrays.stream(array).forEach(value -> {
    
    
        System.out.print(value + " ");
    });
    System.out.println();
}

猜你喜欢

转载自blog.csdn.net/zhaoqingquanajax/article/details/114993758