算法,根据设计方法来分类,可以分为穷举法、分治法、线性规划法、动态规划法、贪心算法、回溯法等。
快速排序采用分治法,原理如下:
快速排序是对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1)、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3)、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4)、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5)、重复第3、4步,直到I=J;
例如:待排序的数组A的值分别是:(初始关键数据X:=49)
A[1] A[2] A[3] A[4] A[5] A[6] A[7]:
49 38 65 97 76 13 27
第一次交换后: 27 38 65 97 76 13 49
( 按照算法的第三步从后面开始找)
第二次交换后: 27 38 49 97 76 13 65
( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时I:=3 )
第三次交换后: 27 38 13 97 76 49 65
( 按照算法的第五步将又一次执行算法的第三步从后开始找)
第四次交换后: 27 38 13 49 76 97 65
( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时J:=4 )
此时再执行第三步的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。
快速排序就是递归调用此过程--再以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列。
1)、设有N(假设N=10)个数,存放在S数组中;
2)、在S[1。。N]中任取一个元素作为比较基准,例如取T=S[1],起目的就是在定出T应在排序结果中的位置K,这个K的位置在:S[1。。K-1]<=S[K]<=S[K+1..N],即在S[K]以前的数都小于S[K],在S[K]以后的数都大于S[K];
3)、利用分治思想(即大化小的策略)可进一步对S[1...K-1]和S[K+1...N]两组数据再进行快速排序直到分组对象只有一个数据为止。
文字太辛苦,看看图:
之前只是进行到这一步,真动手写代码,发现,弱爆了。
……………………
…………
还是写写吧,源码如下:
package dec;
/**
*
*
* <p>
* Title: 快速排序示例代码 /p>
*
* <p>
* Description: 示例 业务类
* </p>
*
* <p>
* Copyright: Copyright (c) 2012
* </p>
*
*
* @author dml@2012-12-6
* @version 1.0
*/
public class QSort {
/**
* @param args
*/
public static void main(String[] args) {
quicksort qs = new quicksort();
int data[] = { 14, 23, 2, 32, 54, 32, 58, 79, 39, 11 };
qs.data = data;
qs.sort(0, qs.data.length - 1);
qs.display();
}
}
class quicksort {
public int data[];
private int partition(int sortArray[], int low, int high) {
int key = sortArray[low];
while (low < high) {
while (low < high && sortArray[high] >= key)
high--;
sortArray[low] = sortArray[high];
while (low < high && sortArray[low] <= key)
low++;
sortArray[high] = sortArray[low];
}
sortArray[low] = key;
return low;
}
public void sort(int low, int high) {
if (low < high) {
int result = partition(data, low, high);
sort(low, result - 1);
sort(result + 1, high);
}
}
public void display() {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]);
System.out.print(" ");
}
}
}
要真这么写就提交了,肯定被骂死,按照步骤来,先写抽象类:
package dec;
/**
*
*
* <p>Title: 快速排序 /p>
*
* <p>Description: 示例 业务类</p>
*
* <p>Copyright: Copyright (c) 2012</p>
*
*
* @author dml@2012-12-6
* @version 1.0
*/
public abstract class QuickSort {
protected abstract int partition(int sortArray[], int low, int high);
public abstract void sort(int low, int high);
public abstract void display();
}
既然是分治法,关键的方法就是怎么分,怎么处理,这个写清楚了,基本也就搞清楚这个算法的实现过程了。
实现类如下:
package dec;
/**
*
*
* <p>
* Title: 快速排序实现类 /p>
*
* <p>
* Description: 示例 业务类
* </p>
*
* <p>
* Copyright: Copyright (c) 2012
* </p>
*
*
* @author dml@2012-12-6
* @version 1.0
*/
public class QuickSortImpl extends QuickSort {
public int data[];
/*
* (non-Javadoc)
*
* @see dec.QuickSort#partition(int[], int, int)
*/
@Override
protected int partition(int[] sortArray, int low, int high) {
int key = sortArray[low];
while (low < high) {
while (low < high && sortArray[high] >= key)
high--;
sortArray[low] = sortArray[high];
while (low < high && sortArray[low] <= key)
low++;
sortArray[high] = sortArray[low];
}
sortArray[low] = key;
return low;
}
/*
* (non-Javadoc)
*
* @see dec.QuickSort#sort(int, int)
*/
@Override
public void sort(int low, int high) {
if (low < high) {
int result = partition(data, low, high);
sort(low, result - 1);
sort(result + 1, high);
}
}
/*
* (non-Javadoc)
*
* @see dec.QuickSort#display()
*/
@Override
public void display() {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]);
System.out.print(" ");
}
}
public static void main(String[] args) {
QuickSortImpl qs = new QuickSortImpl();
int data[] = { 14, 23, 2, 32, 54, 32, 58, 79, 39, 11 };
qs.data = data;
qs.sort(0, qs.data.length - 1);
qs.display();
}
}
运行结果:
2 11 14 23 32 32 39 54 58 79
验证无误,下来就是需要看时间复杂度了。这个等把其它各种排序都写完之后再汇总对比。
dml@wip 2012-12-6