快速排序(Quicksort)的主要思想是,通过某种O(n)的方法,将乱序数组分为左右两部分,使得左边的元素小于右边的元素,然后进行递归。平均来说,复杂度是O(nlog(n)).
方法一(比较繁琐):
快速排序的关键在于如何用O(n)的时间将数组分为左右两部分。不妨设临界元素pivot=array[0],将数组分为比pivot大和小两部分。我们利用两个指针left_index以及right_index,使得下标小于left_index的元素小于等于pivot,下标大于right_index的元素大于pivot。
首先,left_index右移,当遇到大于pivot的元素时,停止右移,将该元素与right_index的元素置换,此时可以将right_index向左移一位。
然后,right_index左移,当遇到小于等于pivot的元素时,停止左移,将该元素与left_index的元素置换,此时可以将left_index向右移一位。
然后,left_index右移 ...
直到left_index < right_index + 1,此时,数组的分割过程结束。(注意:两个指针左右移动的次数是O(n)的)
此时,可以将pivot元素(array[0])与左右的临界点交换。使得数组左边小于pivot,右边大于pivot,可以进行递归了。
方法二(比较简单,详见函数quick_sort_2):
思路:从左边找到第一个大于pivot的元素(下标为left_index),从右边找到第一个小于pivot的元素(下标为right_index),如果left_index<right_index,则交换两个元素。
代码如下
public class import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class QuickSort {
public static int [] random_order_array(int len){
List
list = new ArrayList
();
for (int i = 0; i < len; i ++){
list.add(i);
}
Collections.shuffle(list);
int [] array = new int [len];
for (int i = 0; i < len; i ++)
array[i] = list.get(i);
return array;
}
public static void quick_sort(int [] array, int start, int end){
if (start == end) return;
if (start == end - 1){
if (array[start] > array[end])
swap(array, start, end);
return;
}
int pivot = array[start];
int left_index = start + 1; // array[left_index] 左边的元素(不包含),都小于或者等于pivot
int right_index = end; // array[end_index] 右边的元素(不包含),都严格大于pivot
while (left_index < right_index + 1){
while (left_index < right_index + 1){
if (array[left_index] > pivot){
swap(array, left_index, right_index);
right_index --;
break;
}
left_index ++;
}
while (left_index < right_index + 1){
if (array [right_index] <= pivot){
swap(array, left_index, right_index);
left_index ++;
break;
}
right_index --;
}
}
swap(array, start, left_index - 1);
if (start < left_index - 1) quick_sort(array, start, left_index - 2);
if (end > right_index + 1) quick_sort(array, right_index + 1, end);
}
public static void quick_sort_2(int [] array, int start, int end){
if (start == end) return;
if (start == end - 1){
if (array[start] > array[end])
swap(array, start, end);
return;
}
int pivot = array[start];
int left_index = start + 1;
int right_index = end;
while (true){
while (left_index <= end && array[left_index] < pivot)
left_index ++;
while (right_index > start && array[right_index] > pivot)
right_index --;
if (left_index >= right_index)
break;
swap(array, left_index, right_index);
}
swap(array, start, left_index - 1);
if (start < left_index - 1) quick_sort(array, start, left_index - 2);
if (end > right_index + 1) quick_sort(array, right_index + 1, end);
}
public static final void swap(int [] array, int i, int j){ //内联函数,更快
if (i != j){
array[i] = array[i] ^ array[j];
array[j] = array[i] ^ array[j];
array[i] = array[i] ^ array[j];
}
}
public static void print_array(int [] array){
for (int i = 0; i < array.length; i ++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String [] args){
int len = 20;
int [] array = random_order_array(len);
//int [] array = {8, 4, 0, 6, 1, 9, 3, 7, 2, 5 };
System.out.println("乱序数组:");
print_array(array);
//quick_sort(array, 0, len - 1);
quick_sort_2(array, 0, len - 1);
System.out.println("排序后数组:");
print_array(array);
}
}
另外,C++的实现如下:
# include <iostream>
# include <ctime>
# include <cstdlib>
using namespace std;
int rand_int(int start, int end);
void print_array(int * array, int len);
void quick_sort(int * array, int len);
void swap(int * array, int i, int j);
int * rand_array(int n);
int main(){
srand(time(0));
int len = 20;
int * array = rand_array(len);
print_array(array, len);
quick_sort(array, len);
print_array(array, len);
return 0;
}
void print_array(int * array, int len){
int * temp = array;
for (int i = 0; i < len; i ++){
cout << * (temp ++) << " ";
}
cout << endl;
}
int rand_int(int start, int end){
return start + rand() % (end - start + 1);
}
void quick_sort(int * array, int len){
if (len <= 1) return;
int left_index = 0;
int right_index = len - 1;
for (int w = 0; w < len; w ++){
while (array[left_index] <= array[0] && left_index <= right_index) left_index ++;
while (array[right_index] > array[0] && right_index > left_index) right_index --;
if (left_index >= right_index) break;
swap(array, left_index, right_index);
}
swap(array, 0, left_index - 1);
quick_sort(array, left_index - 1);
quick_sort(array + right_index, len - left_index);
}
void swap(int * array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
int * rand_array(int n){
//生成随机的长度为n的数组
//原理参考了http://blog.csdn.net/taobao755624068/article/details/8522953
int * array = new int[n];
for (int i = 0; i < n; i ++)
array[i] = i;
for (int i = 0; i < n; i ++){
int p = rand_int(0, i);
swap(array, p, i);
}
return array;
}