快速排序
快速排序是排序算法中较优秀的算法,下面将用的递归的形式来实现.
首先是需要的工具类.
工具类
random()功能:给数组赋予随机值.代码:
public static void random(int[] a) {
for(int i = 0; i < a.length; i++) {
a[i] = new Random().nextInt(100)+1;//给数组赋1~100(包括100)的值
}
}
不要忘记导入java.util.Random包.
swap()功能:交换两个下标对应的数组值.代码:
public static void swap(int[] a, int m, int n){
int temp = 0;
temp = a[m];
a[m] = a[n];
a[n] = temp;
}
printf()功能:打印数组,方便更直观的观察数组.代码:
public static void printf(int[] a){
System.out.print("{");
for (int i = 0; i < a.length; i++) {
if (i == a.length - 1)
System.out.print(a[i]);
else
System.out.print(a[i] + " ");
}
System.out.println("}");
}
介绍完工具类,上题.
题目+分析:
题目:用快速排序将一个数组排序.
主元(指你从数组中选出来与其余数比较的一个数)
分析:快速排序的思想是先将比(主元)小的数放一边,比(主元)大的数放另一边.这就将数组一分为二.
然后再将"两份"数组分别再次进行比较就变成"四份"数组,这里可以思考为什么快速排序算法较为优秀.
如果每次运气好都选到处于中间位值的那个数(比这个数大的数与比这个数小的数的个数一样),那么
第一次排序下来可以排好一个数,
第二次就能排好两个+一个数,
第三次就是四个+两个+一个数,
第四次八个数.(图略)
相信大家肯定明白了.随着排序次数增多,每次能排好的数呈"指数爆炸"的形式增长.
了解了原理过后怎么去实现它呢,我们再看看实现的原理:
我们定义两个"指针",这里的指针不是C语言中指向地址的指针,而是数组的下标.
左指针:开始时为0,也就是指向a[0].
右指针:开始时为a.length-1,也就是指向数组的最后一个数.
这时,两个指针相向运动.
移动的条件:左指针指向的数比主元小就向右移动,遇到比主元大的数则停下.
右指针指向的数比主元大就向左移动,遇到比主元小的数则停下.
当两指针停下时,交换两指针所指的数,指针位置不变,交换后,继续移动,直到两指针相错.
两指针最后会相遇,相遇过后,如果left指的数比主元大,那么交换,left向右移动,right向左移动,即,最后两指针会相错.
终于到了最后一步,此时右指针所指的数的左边及自己都是比主元小的数,将右指针的位置与主元的位置交换 ,主元的排序位置就是正确的,接下来就递归重复这个过程就能完成排序.
实现代码:
public class QuickSort {
public static void main(String[] args) {
int a[] = new int[10];//这里以长度为10的数组做实验,根据具体需求可以改动
random(a);//产生随机数组
int p = new Random().nextInt(10);//产生随机主元,这里随机数范围需要跟数组长度一致
printf(a);//打印排序前的数组
quicksort(a, p, a.length-1);
printf(a);//打印排序后的数组
}
public static void quicksort(int[] a, int p, int r) {// a[p]做主元
if (p <= r) {
int q = pivot(a, p, r);//对主元进行排序
quicksort(a, 0, q-1);//对第一次排序后的左边部分再次进行排序
quicksort(a, q+1, r);//对第一次排序后的右边部分再次进行排序
}
}
public static int pivot(int[] a, int p, int r) {
int left = 0;//左指针
int right = r ;//右指针
while (left <= right) {
while (left <= right&&a[left] <= a[p])//这里的left<=right是防止指针越界,例如a[0]为最大的数,left就会指向a[a.length],而a.length并不存在.
left++;
while (right >= left&&a[right] > a[p])//right>=left同上,为防止指针越界
right--;
if (left < right)//最后,left与right相错时不用交换
swap(a, left, right);
}
swap(a, p, right);//交换主元与右指针的数,主元排序完毕
return right;
}