1 问题描述
给定一组数据,使用快速排序得到这组数据的非降序排列。
2 解决方案
2.1 快速排序原理简介
引用自百度百科:
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
具体排序过程:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1(PS:即i从数组前开始向后遍历,j从数组后开始向前遍历);
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]互换;(PS:3)和4)步核心思想就是i向后遍历遇到大于A[0]的元素,停下来等待;j向前遍历遇到小于A[0]的元素,停下来等待;然后交换此时的A[i]和A[j]的值;交换完后,i依旧自增遍历,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-完成的时候,此时令循环结束)。
下面来看一个具体排序示例:
给定一组数据:5,3,1,9,8,2,4,7存入数组中
快速排序性能分析:
package com.liuzhen.chapterFive;
public class Quicksort {
/*
* 该函数功能使用快速排序返回数组A的非降序序列
* 输入数组A[0..n],其子数组为A[start..end]
*/
public static void getQuicksort(int[] A,int start,int end){
if(start < end){
int s = HoarePartition(A,start,end); //s是分裂位置,即排序结果序列的最终位置
getQuicksort(A,start,(s-1));
getQuicksort(A,(s+1),end);
}
}
/*
* 以数组第一个元素为中轴,对子数组进行划分
* 返回分裂点在数组排序结果中的最终位置
*/
public static int HoarePartition(int[] A,int start,int end){
int p = A[start];
int i = start+1;
int j = end;
if(i == j){
if(A[j] >= p) //此时分裂点右方只有一个元素,且大于分裂点处值
return start;
}
while(i < j){
while(A[i] < p){
if(i == end)
break;
i = i+1;
}
while(A[j] >= p){
if(j == (start+1)){
if(A[j] >= p) //此时为分裂点右方全部是大于等于p的元素
return start;
break;
}
j = j-1;
}
swapArray(A,i,j);
}
swapArray(A,i,j); //当i>=j撤换最后一次交换
swapArray(A,j,start);
return j;
}
/*
* 交换数组中两个不同位置上的元素值
*/
public static void swapArray(int[] A,int m,int n){
int temp = A[m];
A[m] = A[n];
A[n] = temp;
}
//初始化一个随机数组
public static int[] initArray(int n){
int[] result = new int[n];
for(int i = 0;i < n;i++)
result[i] = (int)(Math.random()*100); //采用随机函数随机生成1~100之间的数
return result;
}
public static void main(String[] args){
int[] A = initArray(200);
getQuicksort(A,0,(A.length-1));
System.out.println();
for(int i = 0;i < A.length;i++){
if(i%10 == 0)
System.out.println();
System.out.print(A[i]+"\t");
}
}
}
运行结果:
0 0 0 1 1 1 2 2 2
2 3 3 4 4 4 7 7 7
8 8 8 9 9 11 12 12 12
13 14 14 15 15 16 16 17 17
18 19 19 19 20 20 21 23 24
24 24 25 25 25 25 25 26 26
27 27 28 28 28 29 29 29 30
31 31 34 34 34 35 36 37 37
40 40 41 42 42 43 44 44 44
45 45 45 47 48 48 48 50 50
50 50 51 51 52 53 55 55 56
56 57 57 58 58 58 59 60 60
62 63 63 63 64 65 65 65 65
66 67 68 69 69 69 70 70 72
72 74 75 75 76 76 76 76 77
77 78 79 79 80 81 81 81 81
82 82 83 83 84 84 86 86 86
87 87 87 87 87 87 87 87 88
89 89 89 90 92 93 93 93 95
96 96 96 97 98 98 99 99 99
1 问题描述
给定一组数据,使用快速排序得到这组数据的非降序排列。
2 解决方案
2.1 快速排序原理简介
引用自百度百科:
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
具体排序过程:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1(PS:即i从数组前开始向后遍历,j从数组后开始向前遍历);
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]互换;(PS:3)和4)步核心思想就是i向后遍历遇到大于A[0]的元素,停下来等待;j向前遍历遇到小于A[0]的元素,停下来等待;然后交换此时的A[i]和A[j]的值;交换完后,i依旧自增遍历,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-完成的时候,此时令循环结束)。
下面来看一个具体排序示例:
给定一组数据:5,3,1,9,8,2,4,7存入数组中
快速排序性能分析:
package com.liuzhen.chapterFive;
public class Quicksort {
/*
* 该函数功能使用快速排序返回数组A的非降序序列
* 输入数组A[0..n],其子数组为A[start..end]
*/
public static void getQuicksort(int[] A,int start,int end){
if(start < end){
int s = HoarePartition(A,start,end); //s是分裂位置,即排序结果序列的最终位置
getQuicksort(A,start,(s-1));
getQuicksort(A,(s+1),end);
}
}
/*
* 以数组第一个元素为中轴,对子数组进行划分
* 返回分裂点在数组排序结果中的最终位置
*/
public static int HoarePartition(int[] A,int start,int end){
int p = A[start];
int i = start+1;
int j = end;
if(i == j){
if(A[j] >= p) //此时分裂点右方只有一个元素,且大于分裂点处值
return start;
}
while(i < j){
while(A[i] < p){
if(i == end)
break;
i = i+1;
}
while(A[j] >= p){
if(j == (start+1)){
if(A[j] >= p) //此时为分裂点右方全部是大于等于p的元素
return start;
break;
}
j = j-1;
}
swapArray(A,i,j);
}
swapArray(A,i,j); //当i>=j撤换最后一次交换
swapArray(A,j,start);
return j;
}
/*
* 交换数组中两个不同位置上的元素值
*/
public static void swapArray(int[] A,int m,int n){
int temp = A[m];
A[m] = A[n];
A[n] = temp;
}
//初始化一个随机数组
public static int[] initArray(int n){
int[] result = new int[n];
for(int i = 0;i < n;i++)
result[i] = (int)(Math.random()*100); //采用随机函数随机生成1~100之间的数
return result;
}
public static void main(String[] args){
int[] A = initArray(200);
getQuicksort(A,0,(A.length-1));
System.out.println();
for(int i = 0;i < A.length;i++){
if(i%10 == 0)
System.out.println();
System.out.print(A[i]+"\t");
}
}
}
运行结果:
0 0 0 1 1 1 2 2 2
2 3 3 4 4 4 7 7 7
8 8 8 9 9 11 12 12 12
13 14 14 15 15 16 16 17 17
18 19 19 19 20 20 21 23 24
24 24 25 25 25 25 25 26 26
27 27 28 28 28 29 29 29 30
31 31 34 34 34 35 36 37 37
40 40 41 42 42 43 44 44 44
45 45 45 47 48 48 48 50 50
50 50 51 51 52 53 55 55 56
56 57 57 58 58 58 59 60 60
62 63 63 63 64 65 65 65 65
66 67 68 69 69 69 70 70 72
72 74 75 75 76 76 76 76 77
77 78 79 79 80 81 81 81 81
82 82 83 83 84 84 86 86 86
87 87 87 87 87 87 87 87 88
89 89 89 90 92 93 93 93 95
96 96 96 97 98 98 99 99 99