java實現快速排序一種常規的,一種是左程雲的方式。
阿新 • • 發佈:2018-11-16
java實現快速排序:
一:先來一個常規快排:
這個方式就是我們的基準值一直在兩個邊界徘徊,要麼在less的較大邊界,要麼是在more的小邊界,其實就是在居中位置徘徊。
package chapter1; //來一個快排,常規快排 public class QuickSort { public static void main(String[] args) { int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 }; System.out.print("排序前 "); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+" "); } System.out.println(); quickSort(arr, 0, arr.length-1); System.out.print("排序後 "); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+" "); } } public static void quickSort(int[] arr, int low, int high) { if (low < high) { int patition = patition(arr, low, high); quickSort(arr, low, patition-1); quickSort(arr, patition + 1, high); } } public static int patition(int[] arr, int low, int high) { int num = arr[low];// 我們取第一個作為基準值,而且基準值開始是在最低位 while (low < high) { while (low < high && arr[high] > num) { high--; } swap(arr, low, high);//交換後,基準值跑到高位較小的位置了 while (low < high && arr[low] <= num) { low++; } swap(arr, low, high);//交換後,基準值又跑到低位較大位置了 } return low; } private static void swap(int[] arr, int low, int high) { int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; } }
控制檯列印如下:
改進版本:就是添加了排除相等部分的重複排序:
package chapter1; //來一個快排,改進快排,我們多新增一個記錄想等值。 public class QuickSort { public static void main(String[] args) { int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 }; System.out.print("排序前 "); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); quickSort(arr, 0, arr.length - 1); System.out.print("排序後 "); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } public static void quickSort(int[] arr, int low, int high) { if (low < high) { int[] patition = patition(arr, low, high); quickSort(arr, low, patition[0] - patition[1]); quickSort(arr, patition[0] + 1, high); } } public static int[] patition(int[] arr, int low, int high) { int num = arr[low];// 我們取第一個作為基準值 int equal = 0;// 這個用來記錄等於基準值的數量,至少是1 int result[] = new int[2]; while (low < high) { while (low < high && arr[high] > num) { high--; } swap(arr, low, high); while (low < high && arr[low] <= num) { if (arr[low] == num) { equal++; } low++; } swap(arr, low, high); } result[0] = low; result[1] = equal; return result; } private static void swap(int[] arr, int low, int high) { int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; } }
控制檯:
二:左程雲方式的快排
其實就是多了一部分,多了指出相等值的那部分,第二次就不需要再去重複排那些相等值的過程
首先來看一個問題:我們快排第一步是找一個基準值 ,然後右邊值都大於基準值,左邊值都小於基準值。
題目一:我隨意給定一個數組和一個給定值,大於該值放右邊,其他放左邊,同時不能使用多餘陣列
package chapter1; //需求:給一個數組,和其中一個數,將大於這個數和小於這個數的分成兩邊 public class GroupTest { public static void main(String[] args) { int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 }; int num = 6; group(arr, num); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); } } public static void group(int[] arr, int num) { int p = 0; int small = 0;// 小數的邊界 int big = arr.length - 1;// 大數的邊界 while (small < big) { if (arr[p] < num) { exchange(arr, small, p); small++; p++; } else { exchange(arr, big, p); big--; } } } private static void exchange(int[] arr, int q, int p) { // TODO Auto-generated method stub int temp = arr[p]; arr[p] = arr[q]; arr[q] = temp; } }
控制檯:
通常我們選取最後一個或者第一個值為我們的基準值。下邊我們選取最後一個值作為基準值,而且如果我們使用了把中間值拿過來放著後邊不做比較,那麼我們比較次數會更少一點
題目二:給定一個整型陣列,然後以最後一個數為基準,將大於基準值的放右邊,小於基準值放到左邊。最後陣列的情況就是,在基準值兩邊,一邊是全部大於基準值,一邊是全部小於基準值;
我們使用三個指標來區分三塊,一塊是小於區域,中間是等於區域,右邊是大於區域。開始的時候,小於和大於區域都是在陣列外邊,要是存在一個符合要求的,就放到相應區域,同時該區域長度就增加1。如果是有一個小於的,首先交換當前值和less後邊那個值,那麼小於的區域的指標就++less,同時也會推著中間部分往右邊跑,所以當前指標cur++;如果是滿足大於區域,就把當前cur指向的數和大於那邊的區域的邊界more前邊的那個數值交換,同時大於區域增加,就是--more,但是這裡我們的cur就不變化。
程式碼:
package test2018926;
public class QuickSort {
public static void main(String[] args) {
Integer[] arr = { 1, 2, 7, 5, 4, 3 };
partition(arr, 0, arr.length - 1);
}
public static Integer[] partition(Integer[] arr, int L, int R) {
// 使用三個指標來將我們的資料分成三類,
int cur = L;// 這個指向當前資料
int less = L - 1;// 小數的前面一個
int more = R + 1;// 大數的後邊一個
int num = arr[arr.length - 1];// 以最後一個值為基準來排出大於和小於
Integer[] arr1 = new Integer[2];
while (cur < more) {
// System.out.println(cur);
if (arr[cur] > num) {
swap(arr, cur, --more);
} else if (arr[cur] < num) {
swap(arr, cur++, ++less);// less位置增加一個,就會推著cur向後
} else {
cur++;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
arr1[0] = less + 1;//等於num的左邊界
arr1[1] = more - 1;//等於num的右邊界
return arr1;
}
// 交換陣列位置
private static void swap(Integer[] arr, Integer m, Integer n) {
int temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
}
控制檯列印:
題目三:下邊講解我們的改進快排:
快排就是不斷細分,對一個小部分都進行上邊相同的操作。
開始分為兩邊,然後對兩邊分別再分兩邊,一直分到最小,就是分成單個為止。
package test2018926;
public class QuickSort {
public static void main(String[] args) {
Integer[] arr = { 1, 2, 7, 5, 4, 3 };
quickSort(arr, 0, arr.length - 1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
public static void quickSort(Integer[] arr, int L, int R) {
if (L < R) {
Integer[] p = partition(arr, L, R);// 返回的是相同數值區域的兩個邊界
quickSort(arr, L, p[0] - 1);//p[0]是等於部分的左邊界
quickSort(arr, p[1] + 1, R);//p[1]是等於部分的右邊界
}
}
public static Integer[] partition(Integer[] arr, int L, int R) {
// 使用三個指標來將我們的資料分成三類,
int cur = L;// 這個指向當前資料
int less = L - 1;// 小數的前面一個
int more = R + 1;// 大數的後邊一個
int num = arr[arr.length - 1];// 以最後一個值為基準來排出大於和小於
Integer[] arr1 = new Integer[2];
while (cur < more) {
// System.out.println(cur);
if (arr[cur] > num) {
swap(arr, cur, --more);
} else if (arr[cur] < num) {
swap(arr, cur++, ++less);// less位置增加一個,就會推著cur向後
} else {
cur++;
}
}
for (int i = 0; i < arr.length; i++) {
// System.out.print(arr[i]);
}
arr1[0] = less + 1;
arr1[1] = more - 1;
return arr1;
}
// 交換陣列位置
private static void swap(Integer[] arr, Integer m, Integer n) {
int temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
}
控制檯列印: