欢迎Java爱好者品读其他算法详解:
简单比较排序:http://blog.csdn.net/ysjian_pingcx/article/details/8652091
冒泡排序: http://blog.csdn.net/ysjian_pingcx/article/details/8653732
选择排序: http://blog.csdn.net/ysjian_pingcx/article/details/8656048
直接插入排序:http://blog.csdn.net/ysjian_pingcx/article/details/8674454
快速排序: http://blog.csdn.net/ysjian_pingcx/article/details/8687444
int[] array = { 9, 5, 6, 8, 4, 3, 2, 7, 1 };
int[] array = { 1, 5, 6, 8, 4, 3, 2, 7, 9 };
int mid = (low + high) / 2;
//枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
//交换左端与右端的记录,保证左端较小
swap(low, high, array);
}
if (array[mid] > array[high]) {
//交换中间与右端的记录,保证中间较小
swap(mid, high, array);
}
if (array[mid] > array[low]) {
//交换左端与中间的记录,保证左端较小
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
//枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
//交换左端与右端的记录,保证左端较小
swap(low, high, array);
}
if (array[mid] > array[high]) {
//交换中间与右端的记录,保证中间较小
swap(mid, high, array);
}
if (array[mid] > array[low]) {
//交换左端与中间的记录,保证左端较小
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
swap(low, high, array); // 把比枢轴记录小的值交换到低端
while (low < high && array[low] <= pivotKey) {
low++;
}
swap(low, high, array); // 把比枢轴记录大的值交换到高端
}
return low; // 返回枢轴记录的下标
}
@就在原来的基础上加上选取左中右三个记录,并进行排序后去中间的数赋给枢轴记录;
int pivotKey = array[low]; // 将数组的第一个元素作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
swap(low, high, array);// 把比枢轴记录小的值交换到低端
while (low < high && array[low] <= pivotKey) {
low++;
}
swap(low, high, array);// 把比枢轴记录大的值交换到高端
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
array[low] = array[high]; // 把比枢轴记录小的值赋给low下标的记录
while (low < high && array[low] <= pivotKey) {
low++;
}
array[high] = array[low]; // 把比枢轴记录大的值赋给high下标的记录
array[low] = pivotKey; // 然后将枢轴记录赋给low
}
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
//枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
swap(low, high, array);
}
if (array[mid] > array[high]) {
swap(mid, high, array);
}
if (array[mid] > array[low]) {
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
array[low] = array[high]; // 把比枢轴记录小的值赋给low下标的记录
while (low < high && array[low] <= pivotKey) {
low++;
}
array[high] = array[low]; // 把比枢轴记录大的值赋给high下标的记录
array[low] = pivotKey; // 然后将枢轴记录赋给low
}
return low; // 返回枢轴记录的下标
}
@上面采取三数取中和省略不必要的交换两种优化;
/**
* 快速排序的递归调用
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
quickSort(pivot + 1, high, array); // 对高子表进行递归排序
}
}
@判断条件是if(low < high) 然后,获取枢轴记录,分别对两端进行递归调用,这里可以优化:
/**
* 快速排序的尾递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
while (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
low = pivot + 1; // 尾递归
}
}
@这一这里相当于方法quickSor在执行一次时,用了while(low < high)这个循环条件,这里就是关键所在
4.小数组的优化:
/**
* 快速排序的尾递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (high - low > DIVISION) {//当长度小于分界点时调用快速排序
while (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
low = pivot + 1; // 尾递归
}
}else {
insertSort(array);
}
}
@DIVISION是一个分界点常量:
/**
* 定义一个分界点常量
*/
private final int DIVISION = 50;
@insertSort(array):
/**
* 直接插入排序的核心程序
* @param array
*/
public void insertSort(int... array) {
int length = array.length;
// 此循环从1开始,就是将0下标的元素当做一个参照
for (int i = 1; i < length; i++) {
if (array[i] < array[i - 1]) { // 将当前下标的值与参照元素比较,如果小于就进入里面
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
int sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
// 这个循环很关键,从当前下标之前一个元素开始倒序遍历,比较结果如果比当前大的,就后移
for (int j = i - 1; j >= 0 && array[j] > sentry; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置
}
}
}
下面是四种优化版本的完整代码实现:
1.枢轴选取优化:
/**
* 优化枢轴值的快速排序法
*
* @author PingCX
*
*/
public class QuickSortOptPivot {
public static void main(String[] args) {
QuickSortOptPivot qComplete = new QuickSortOptPivot();
int[] array = { 9, 5, 6, 8, 4, 3, 2, 7, 1 };
System.out.println(Arrays.toString(array));
qComplete.quickSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
System.out.println(qComplete.getMid(25, 90, 13));
}
/**
* 快速排序的入口
*
* @param array
*/
public void quickSort(int... array) {
quickSort(0, array.length - 1, array);
}
/**
* 快速排序的递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
quickSort(pivot + 1, high, array); // 对高子表进行递归排序
}
}
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
//枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
//交换左端与右端的记录,保证左端较小
swap(low, high, array);
}
if (array[mid] > array[high]) {
//交换中间与右端的记录,保证中间较小
swap(mid, high, array);
}
if (array[mid] > array[low]) {
//交换左端与中间的记录,保证左端较小
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
swap(low, high, array); // 把比枢轴记录小的值交换到低端
while (low < high && array[low] <= pivotKey) {
low++;
}
swap(low, high, array); // 把比枢轴记录大的值交换到高端
}
return low; // 返回枢轴记录的下标
}
/**
* 内部实现,用于交换数组的两个引用值
*
* @param beforeIndex
* @param afterIndex
* @param arr
*/
private void swap(int oneIndex, int anotherIndex, int[] array) {
int temp = array[oneIndex];
array[oneIndex] = array[anotherIndex];
array[anotherIndex] = temp;
}
/**
* 交换优化的快速排序法
*
* @author PingCX
*
*/
public class QuickSortOptExchange {
public static void main(String[] args) {
QuickSortOptExchange qComplete = new QuickSortOptExchange();
int[] array = { 25, 36, 21, 45, 13};
System.out.println(Arrays.toString(array));
qComplete.quickSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
System.out.println(qComplete.getMid(25, 90, 13));
}
/**
* 快速排序的入口
*
* @param array
*/
public void quickSort(int... array) {
quickSort(0, array.length - 1, array);
}
/**
* 快速排序的递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
quickSort(pivot + 1, high, array); // 对高子表进行递归排序
}
}
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
//枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
swap(low, high, array);
}
if (array[mid] > array[high]) {
swap(mid, high, array);
}
if (array[mid] > array[low]) {
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
array[low] = array[high]; // 把比枢轴记录小的值赋给low下标的记录
while (low < high && array[low] <= pivotKey) {
low++;
}
array[high] = array[low]; // 把比枢轴记录大的值赋给high下标的记录
array[low] = pivotKey; // 然后将枢轴记录赋给low
}
return low; // 返回枢轴记录的下标
}
/**
* 内部实现,用于交换数组的两个引用值
*
* @param beforeIndex
* @param afterIndex
* @param arr
*/
private void swap(int oneIndex, int anotherIndex, int[] array) {
int temp = array[oneIndex];
array[oneIndex] = array[anotherIndex];
array[anotherIndex] = temp;
}
3.递归操作优化:
/**
* 递归优化的快速排序法
*
* @author PingCX
*
*/
public class QuickSortOptRec {
private final int DIVISION = 50;
public static void main(String[] args) {
QuickSortOptRec qComplete = new QuickSortOptRec();
int[] array = { 25, 36, 21, 45, 13 };
System.out.println(Arrays.toString(array));
qComplete.quickSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
System.out.println(qComplete.getMid(25, 90, 13));
}
/**
* 快速排序的入口
*
* @param array
*/
public void quickSort(int... array) {
quickSort(0, array.length - 1, array);
}
/**
* 快速排序的尾递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (high - low < DIVISION) {//当长度小于分界点时调用快速排序
while (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
low = pivot + 1; // 尾递归
}
}
}
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
// 枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
swap(low, high, array);
}
if (array[mid] > array[high]) {
swap(mid, high, array);
}
if (array[mid] > array[low]) {
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
array[low] = array[high]; // 把比枢轴记录小的值赋给low下标的记录
while (low < high && array[low] <= pivotKey) {
low++;
}
array[high] = array[low]; // 把比枢轴记录大的值赋给high下标的记录
array[low] = pivotKey; // 然后将枢轴记录赋给low
}
return low; // 返回枢轴记录的下标
}
/**
* 内部实现,用于交换数组的两个引用值
*
* @param beforeIndex
* @param afterIndex
* @param arr
*/
private void swap(int oneIndex, int anotherIndex, int[] array) {
int temp = array[oneIndex];
array[oneIndex] = array[anotherIndex];
array[anotherIndex] = temp;
}
4.最终优化:
/**
* 最终优化的快速排序法
*
* @author PingCX
*
*/
public class QuickSortOptAll {
/**
* 定义一个分界点常量
*/
private final int DIVISION = 50;
public static void main(String[] args) {
QuickSortOptAll qComplete = new QuickSortOptAll();
int[] array = { 25, 36, 21, 45, 13 };
System.out.println(Arrays.toString(array));
qComplete.quickSort(array);// 调用快速排序的方法
System.out.println(Arrays.toString(array));// 打印排序后的数组元素
System.out.println(qComplete.getMid(25, 90, 13));
}
/**
* 快速排序的入口
*
* @param array
*/
public void quickSort(int... array) {
quickSort(0, array.length - 1, array);
}
/**
* 快速排序的尾递归调用
*
* @param low
* @param high
* @param array
*/
private void quickSort(int low, int high, int... array) {
if (high - low > DIVISION) {//当长度小于分界点时调用快速排序
while (low < high) {
int pivot = partition(low, high, array); // 找到枢轴记录的下标
quickSort(low, pivot - 1, array); // 对低子表进行递归排序
low = pivot + 1; // 尾递归
}
}else {
insertSort(array);
}
}
/**
* 优化后快速排序的核心程序,枢轴记录用了三取一,去前中后三个数中间那个
*
* @param low
* @param high
* @param array
* @return 返回枢轴记录
*/
private int partition(int low, int high, int... array) {
int mid = (low + high) / 2;
// 枢轴记录三取一,优化的代码,用于待排序数组元素不是很大的时候
{
if (array[low] > array[high]) {
swap(low, high, array);
}
if (array[mid] > array[high]) {
swap(mid, high, array);
}
if (array[mid] > array[low]) {
swap(mid, low, array);
}
}
int pivotKey = array[low]; // 将三取一后的中间值作为枢轴记录
while (low < high) {
while (low < high && array[high] >= pivotKey) {
high--;
}
array[low] = array[high]; // 把比枢轴记录小的值赋给low下标的记录
while (low < high && array[low] <= pivotKey) {
low++;
}
array[high] = array[low]; // 把比枢轴记录大的值赋给high下标的记录
array[low] = pivotKey; // 然后将枢轴记录赋给low
}
return low; // 返回枢轴记录的下标
}
/**
* 直接插入排序的核心程序
* @param array
*/
public void insertSort(int... array) {
int length = array.length;
// 此循环从1开始,就是将0下标的元素当做一个参照
for (int i = 1; i < length; i++) {
if (array[i] < array[i - 1]) { // 将当前下标的值与参照元素比较,如果小于就进入里面
int vacancy = i; // 用于记录比较过程中那个空缺出来的位置
int sentry = array[i]; // 设置哨兵,将当前下标对应的值赋给哨兵
// 这个循环很关键,从当前下标之前一个元素开始倒序遍历,比较结果如果比当前大的,就后移
for (int j = i - 1; j >= 0 && array[j] > sentry; j--) {
vacancy = j;
array[j + 1] = array[j]; // 后移比当前元素大的元素
}
array[vacancy] = sentry; // 将哨兵,也就是当前下标对应的值置入空缺出来的位置
}
}
}
/**
* 内部实现,用于交换数组的两个引用值
*
* @param beforeIndex
* @param afterIndex
* @param arr
*/
private void swap(int oneIndex, int anotherIndex, int[] array) {
int temp = array[oneIndex];
array[oneIndex] = array[anotherIndex];
array[anotherIndex] = temp;
}
欢迎Java爱好者品读其他算法详解:
简单比较排序:http://blog.csdn.net/ysjian_pingcx/article/details/8652091
冒泡排序: http://blog.csdn.net/ysjian_pingcx/article/details/8653732
选择排序: http://blog.csdn.net/ysjian_pingcx/article/details/8656048
直接插入排序:http://blog.csdn.net/ysjian_pingcx/article/details/8674454
快速排序: http://blog.csdn.net/ysjian_pingcx/article/details/8687444