紀錄網路上大大的程式來源
以下程式都是複製貼上,只有增加print來看結果。
教學來源:
2.8.1 QuickSort Algorithm
程式來源:
快速排序法(Quick Sort)
QuickSort
pivot 值 就是 以這個數 當 基準 . 左邊要比 pivot 值 小 , 右邊要比 pivot 值 大
練習1:pivot取最前面arr[low]
class QuickSort {
int partition(int arr[], int low, int high) {
int pivot = arr[low];
int i = low, j = high;
while (i < j) {
try {
while (arr[i] <= pivot) i++;
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
i = high;
}
while (arr[j] > pivot) j--;
if (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
System.out.print("交換:");
printArray(arr);
} else {
break;
}
}
int temp = arr[low];
arr[low] = arr[j];
arr[j] = temp;
System.out.print("交換:找到pivot值(陣列索引):");
System.out.print(j);
System.out.print(",陣列:");
printArray(arr);
return j;
}
void sort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
sort(arr, low, pi-1);
sort(arr, pi + 1, high);
}
}
/*印陣列*/
static void printArray(int arr[]) {
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
}
class Main {
public static void main(String[] args) {
int arr[] = {1,3,5,7,9,11,13,15,17};
int n = arr.length;
QuickSort ob = new QuickSort();
ob.sort(arr, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr);
System.out.println();
int arr1[] = {3,98,80,5,57,8,9};
n = arr1.length;
ob.sort(arr1, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr1);
}
}
交換:找到pivot值(陣列索引):0 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):1 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):2 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):3 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):4 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):5 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):6 ,陣列: 1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):7 ,陣列: 1 3 5 7 9 11 13 15 17
最後排序結果: 1 3 5 7 9 11 13 15 17
// worst 時間複雜度 就很明顯 是 n * n
// 因為有 n個數, 每次檢查的數字 會是 n-1 ...n-2 ...n-3
// int arr1[] = {3,98,80,5,57,8,9};
交換:找到pivot值(陣列索引):0, 陣列: 3 98 80 5 57 8 9
交換:找到pivot值(陣列索引):6, 陣列: 3 9 80 5 57 8 98
交換:3 9 8 5 57 80 98
交換:找到pivot值(陣列索引):3, 陣列: 3 5 8 9 57 80 98
交換:找到pivot值(陣列索引):1, 陣列: 3 5 8 9 57 80 98
交換:找到pivot值(陣列索引):2, 陣列: 3 5 8 9 57 80 98
交換:找到pivot值(陣列索引):4, 陣列: 3 5 8 9 57 80 98
交換:找到pivot值(陣列索引):5, 陣列: 3 5 8 9 57 80 98
最後排序結果:3 5 8 9 57 80 98
練習2,pivot取中間,arr[low + (high - low) / 2]
程式是錯的:
class QuickSort {
int partition(int arr[], int low, int high) {
int pivot = arr[low + (high - low) / 2];
int i = low, j = high;
while (i < j) {
try {
while (arr[i] <= pivot) i++;
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
i = high;
}
while (arr[j] > pivot) j--;
if (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
System.out.print("交換:");
printArray(arr);
} else {
break;
}
}
int temp = arr[low + (high - low) / 2];
arr[low + (high - low) / 2] = arr[j];
arr[j] = temp;
System.out.print("交換:找到pivot值(陣列索引):");
System.out.print(j);
System.out.print(",陣列:");
printArray(arr);
return j;
}
void sort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
sort(arr, low, pi);
sort(arr, pi + 1, high);
}
}
/*印陣列*/
static void printArray(int arr[]) {
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
}
class Main {
public static void main(String[] args) {
int arr[] = {1,3,5,7,9,11,13,15,17};
int n = arr.length;
QuickSort ob = new QuickSort();
ob.sort(arr, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr);
System.out.println();
int arr1[] = {3,98,80,5,57,8,9};
n = arr1.length;
ob.sort(arr1, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr1);
}
}
交換:找到pivot值(陣列索引):4, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):2, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):1, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):0, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):3, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):6, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):5, 陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):7, 陣列:1 3 5 7 9 11 13 15 17
最後排序結果:1 3 5 7 9 11 13 15 17
// 猜測這個狀況 是 最好的時間複雜度 ? 因為 pivot值 每次sort後 都在中間
//
交換:3 5 80 98 57 8 9
交換:找到pivot值(陣列索引):1,陣列:3 98 80 5 57 8 9
交換:找到pivot值(陣列索引):0,陣列:3 98 80 5 57 8 9
交換:3 98 9 5 57 8 80
交換:找到pivot值(陣列索引):5,陣列:3 98 9 5 8 57 80
交換:3 98 5 9 8 57 80
交換:找到pivot值(陣列索引):2,陣列:3 98 9 5 8 57 80
交換:找到pivot值(陣列索引):4,陣列:3 98 9 5 8 57 80
交換:找到pivot值(陣列索引):3,陣列:3 98 9 5 8 57 80
最後排序結果:3 98 9 5 8 57 80
練習3,pivot取後面,arr[high]
class QuickSort {
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = low, j = high;
while (i < j) {
while (arr[i] < pivot) i++;
try {
while (arr[j] >= pivot) j--;
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
j = low;
}
if (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
System.out.print("交換:");
printArray(arr);
} else {
break;
}
}
int temp = arr[high];
arr[high] = arr[i];
arr[i] = temp;
System.out.print("交換:找到pivot值(陣列索引):");
System.out.print(i);
System.out.print(",陣列:");
printArray(arr);
return i;
}
void sort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
sort(arr, low, pi-1);
sort(arr, pi + 1, high);
}
}
/*印陣列*/
static void printArray(int arr[]) {
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
}
class Main {
public static void main(String[] args) {
int arr[] = {1,3,5,7,9,11,13,15,17};
int n = arr.length;
QuickSort ob = new QuickSort();
ob.sort(arr, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr);
System.out.println();
int arr1[] = {3,98,80,5,57,8,9};
n = arr1.length;
ob.sort(arr1, 0, n - 1);
System.out.print("最後排序結果:");
ob.printArray(arr1);
}
}
交換:找到pivot值(陣列索引):8,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):7,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):6,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):5,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):4,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):3,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):2,陣列:1 3 5 7 9 11 13 15 17
交換:找到pivot值(陣列索引):1,陣列:1 3 5 7 9 11 13 15 17
最後排序結果:1 3 5 7 9 11 13 15 17
交換:3 8 80 5 57 98 9
交換:3 8 5 80 57 98 9
交換:找到pivot值(陣列索引):3,陣列:3 8 5 9 57 98 80
交換:找到pivot值(陣列索引):5,陣列:3 8 5 9 57 80 98
交換:找到pivot值(陣列索引):6,陣列:3 8 5 9 57 80 98
交換:找到pivot值(陣列索引):4,陣列:3 8 5 9 57 80 98
交換:找到pivot值(陣列索引):1,陣列:3 5 8 9 57 80 98
交換:找到pivot值(陣列索引):2,陣列:3 5 8 9 57 80 98
最後排序結果:3 5 8 9 57 80 98
問題:好像目前只有中間pivot的錯誤,其他的可以跑
後來有看這些:
Hoare’s vs Lomuto partition scheme in QuickSort
https://www.geeksforgeeks.org/hoares-vs-lomuto-partition-scheme-quicksort/?ref=rp
Quicksort
https://www.raywenderlich.com/books/data-structures-algorithms-in-swift/v3.0/chapters/34-quicksort
Quicksort大概有三種:
Lomuto’s partitioning :挑陣列的最後一項當pivot, 把比pivot小的放到前半段
Hoare’s partitioning :挑陣列的第一項當pivot,陣列左邊挑比pivot大的值,右邊挑比pivot小的值互換
Dutch national flag partitioning :比pivot小的放左邊,相等的不動,大的放右邊.如果一個陣列只有三個數字,只要跑一次迴圈. pivot放哪應該都可以
程式參考:
Comparison Sort: Merge Sort(合併排序法)
教學參考:
Merge Sort | GeeksforGeeks
2.7.2. Merge Sort Algorithm
照抄:
#include <iostream>
#include <vector>
const int Max = 1000;
class MergeMain {
public: void Merge(std::vector < int > & Array, int front, int mid, int end) {
std::vector < int > LeftSub(Array.begin() + front, Array.begin() + mid + 1),
RightSub(Array.begin() + mid + 1, Array.begin() + end + 1);
LeftSub.insert(LeftSub.end(), Max);
RightSub.insert(RightSub.end(), Max);
int idxLeft = 0, idxRight = 0;
for (int i = front; i <= end; i++) {
if (LeftSub[idxLeft] <= RightSub[idxRight]) {
Array[i] = LeftSub[idxLeft];
idxLeft++;
} else {
Array[i] = RightSub[idxRight];
idxRight++;
}
}
std::cout << "process:\n";
PrintArray(Array);
}
public: void MergeSort(std::vector < int > & array, int front, int end) {
if (front < end) {
int mid = (front + end) / 2;
MergeSort(array, front, mid);
MergeSort(array, mid + 1, end);
Merge(array, front, mid, end);
}
}
public: void PrintArray(std::vector < int > & array) {
for (int i = 0; i < array.size(); i++) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
}
};
int main() {
MergeMain mergemain;
int arr[] = {5,3,8,6,2,7,1,4};
std::cout << " arr+sizeof(arr):" << arr + sizeof(arr) << "\n";
std::cout << " sizeof(int):" << sizeof(int) << "\n";
std::vector < int > array(arr, arr + sizeof(arr) / sizeof(int));
std::cout << "original:\n";
mergemain.PrintArray(array);
mergemain.MergeSort(array, 0, 7);
std::cout << "sorted:\n";
mergemain.PrintArray(array);
return 0;
}
結果:
arr+sizeof(arr):0x7ffff7a8d940
sizeof(int):4
original:
5 3 8 6 2 7 1 4
process:
3 5 8 6 2 7 1 4
process:
3 5 6 8 2 7 1 4
process:
3 5 6 8 2 7 1 4
process:
3 5 6 8 2 7 1 4
process:
3 5 6 8 2 7 1 4
process:
3 5 6 8 1 2 4 7
process:
1 2 3 4 5 6 7 8
sorted:
1 2 3 4 5 6 7 8
程式來源:
Comparison Sort: Heap Sort(堆積排序法)
教學來源:
2.6.3 Heap - Heap Sort - Heapify - Priority Queues
Heap Sort | GeeksforGeeks
結果:
original:
9 4 1 6 7 3 8 2 5
original max heap :
0 9 7 8 6 4 3 1 2 5
process :
0 8 7 5 6 4 3 1 2 9
process :
0 7 6 5 2 4 3 1 8 9
process :
0 6 4 5 2 1 3 7 8 9
process :
0 5 4 3 2 1 6 7 8 9
process :
0 4 2 3 1 5 6 7 8 9
process :
0 3 2 1 4 5 6 7 8 9
process :
0 2 1 3 4 5 6 7 8 9
process :
0 1 2 3 4 5 6 7 8 9
sorted:
1 2 3 4 5 6 7 8 9
ascending order:遞增
ex:1 5 7
non-decreasing order: 不會遞減
ex:1 5 5 7
教學和程式來源:
[演算法] 希爾排序法(Shell Sort)
Shell Sort | GeeksforGeeks
Day11 -- Decrease and Conquer - Shell Sort
程式:
index.html
<!DOCTYPE html>
<html>
<head>
<title>shell sort</title>
</head>
<body>
<script src="script.js"></script>
<script>
var numbers = [1,2,8,4,4,3,5,5];
shellSort(numbers);
</script>
</body>
</html>
script.js
var swap = function(data, i, j){
var tmp = data[i];
data[i] = data[j];
data[j] = tmp;
};
var shellSort = function(data){
console.log("ori data:",data)
var gap = parseInt(data.length/2);
while(gap>0){
for(var k = 0; k < gap; k++){
for(var i = k + gap; i < data.length; i += gap){
for(var j = i - gap; j >= k; j -= gap){
if(data[j] > data[j+gap])
swap( data, j, j+gap);
else
break;
}
}
}
gap = parseInt(gap/= 2);
}
console.log("res data:",data)
};
結果
ori data: [ 1, 2, 8, 4, 4, 3, 5, 5 ]
res data: [ 1, 2, 3, 4, 4, 5, 5, 8 ]
教學和程式來源:
[演算法] 基數排序(Radix Sort)
Radix Sort Algorithm Introduction in 5 Minutes
Data Structures and Algorithms in Swift: Radix Sort
筆記:
1 swift的 array.flatMap可以把二維陣列變成一維陣列
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Radix Sort</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script src="script.js"></script>
<script>
var numbers = [89,10,84,4];
radixSort(numbers);
</script>
</body>
</html>
var initArray = function(buckets, count) {
for (var i = 0; i < buckets.length; i++) {
buckets[i] = new Array(buckets.length);
count[i] = 0;
}
}
var radixSort = function(data) {
console.log("ori data:", data)
var MAX = 100;
var dataIndex = 0,
radix = 1;
var buckets = new Array(10), // 桶子 //可以放數字0 到 9
count = new Array(data.length);
initArray(buckets, count);
while (radix <= MAX) {
// 分配
for (var i = 0; i < data.length; i++) {
var LSD = parseInt((data[i] / radix)) % 10;
buckets[LSD][ count[LSD] ] = data[i]; //前面的LSD代表哪個桶子 ,後面的count[LSD],代表桶子裡有幾個東西
count[LSD]++;
}
radix *= 10;
// 合併
dataIndex = 0;
for (var i = 0; i < 10; i++) {
if (buckets[i][count[0]] != 0) {
for (var j = 0; j < count[i]; j++) {
data[dataIndex++] = buckets[i][j];
}
}
count[i] = 0;
}
console.log("turn data:", data)
}
console.log("res data:", data)
};
結果:
ori data: [ 89, 10, 84, 4 ]
turn data: [ 10, 84, 4, 89 ]
turn data: [ 4, 10, 84, 89 ]
turn data: [ 4, 10, 84, 89 ]
res data: [ 4, 10, 84, 89 ]
教學和程式來源:Learn Counting Sort Algorithm in LESS THAN 6 MINUTES!
計數排序法(Counting Sort),只需線性時間就能完成的超快排序法
Day20 -- Time and Space Tradeoff- Distribution Sorting
class CountingSort {
static void countingSortStable(final int[] array, final int min, final int max) {
final int size = max - min + 1;
final int[] count = new int[size]; //索引是數字 ,值是次數
for (final int n: array) {
count[n - min]++;
}
for (int i = 1; i < size; ++i) {
count[i] += count[i - 1];
}
final int[] origin = array.clone(); //array.clone類似複製的功能 ,原本沒排序的陣列複製一份
for (int i = array.length - 1; i >= 0; --i) { //倒著走
final int n = origin[i];
array[--count[n - min]] = n;
}
}
/*印陣列*/
static void printArray(int arr[]) {
int n = arr.length;
for (int i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
}
class Main {
public static void main(String[] args) {
int arr[] = {3,8,7,5,5,8,9};
int n = arr.length;
CountingSort.countingSortStable(arr, 0, 10);
System.out.println("結果:");
CountingSort.printArray(arr);
}
}
結果:
結果:
3 5 5 7 8 8 9