https://juejin.im/post/5b95da8a5188255c775d8124#heading-4
1. 冒泡排序Bubble Sort
每次冒出一个最大的到最后一位
public void bbsort(int[] arr){ int le = arr.length; for(int i = 0; i < le - 1; i++){ for(int j = 0; j < le - i - 1; j++){ if(arr[j] > arr[j+1]) swap(arr, j, j+1); } } }
public void swapbycount(int[] arr, int a, int b){ arr[a] = arr[a] + arr[b]; arr[b] = arr[a] - arr[b]; arr[a] = arr[a] - arr[b]; }
还可以byBit
public static void swapByBitOperation(int[] array, int i, int j) { array[i] = array[i]^array[j]; array[j] = array[i]^array[j]; //array[i]^array[j]^array[j]=array[i] array[i] = array[i]^array[j]; //array[i]^array[j]^array[i]=array[j] } 作者:foofoo 链接:https://juejin.im/post/5b95da8a5188255c775d8124 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2. 快速排序 quick sort
https://www.geeksforgeeks.org/quick-sort/
每次把最右边作为pivot,然后把比pivot小的数放在左边,大的放在右边,这样pivot就放在了应该放的位置。
快速排序也用到了分治法,每次都是先得到pivot应该在的位置,然后sort(arr, left, pivot-1), sort(arr, pivot+1, right)
partition是来求pivot的位置,partition(int arr[ ], int low, int high)
从循环从low到high - 1,有两个指针i和j,i 指向smaller element,初始化是i = low - 1,, j = low表示当前element
如果小于pivot,就i++,然后swap i 和 j的element
最终pivot 和arr[i + 1]互换,返回i+1
/* This function takes last element as pivot, places the pivot element at its correct position in sorted array, and places all smaller (smaller than pivot) to left of pivot and all greater elements to right of pivot */ int partition(int arr[], int low, int high) { int pivot = arr[high]; int i = (low-1); // index of smaller element for (int j=low; j<high; j++) { // If current element is smaller than the pivot if (arr[j] < pivot) { i++; // swap arr[i] and arr[j] int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } // swap arr[i+1] and arr[high] (or pivot) int temp = arr[i+1]; arr[i+1] = arr[high]; arr[high] = temp; return i+1; } /* The main function that implements QuickSort() arr[] --> Array to be sorted, low --> Starting index, high --> Ending index */ void sort(int arr[], int low, int high) { if (low < high) { /* pi is partitioning index, arr[pi] is now at right place */ int pi = partition(arr, low, high); // Recursively sort elements before // partition and after partition sort(arr, low, pi-1); sort(arr, pi+1, high); } }
3. 插入排序 insertion sort
从第二个数开始,每次把当前的数放在合适的位置(通过和前面的数比较)
public void insertionSort(int[ ] arr){ int le = arr.length; for(int i = 1; i < le; i++){ int j = i-1; int tmp = arr[i]; while(j >= 0 && arr[i] < arr[j]){ a[j+1] = a[j]; j--; } a[j+1] = tmp; } }
4. 希尔排序ShellSort
改进版的插入排序
每次用gap来对数组分组,在组内进行插入排序,gap by default == n / 2, 当gap == 1时排序完成就结束了
https://www.geeksforgeeks.org/shellsort/
int sort(int arr[]) { int n = arr.length; // Start with a big gap, then reduce the gap for (int gap = n/2; gap > 0; gap /= 2) { // Do a gapped insertion sort for this gap size. // The first gap elements a[0..gap-1] are already // in gapped order keep adding one more element // until the entire array is gap sorted for (int i = gap; i < n; i += 1) { // add a[i] to the elements that have been gap // sorted save a[i] in temp and make a hole at // position i int temp = arr[i]; // shift earlier gap-sorted elements up until // the correct location for a[i] is found int j; for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) arr[j] = arr[j - gap]; // put temp (the original a[i]) in its correct // location arr[j] = temp; } } return 0; }
5. 选择排序 selection sort
每次把当前数与后面所有的数对比并替换成最小的数
public class SelectSort { public static void sort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { int min = i; for (int j = i+1; j < arr.length; j ++) { //选出之后待排序中值最小的位置 if (arr[j] < arr[min]) { min = j; } } if (min != i) { arr[min] = arr[i] + arr[min]; arr[i] = arr[min] - arr[i]; arr[min] = arr[min] - arr[i]; } } }
6. 归并排序 merge sort
用了divide and conquer分治法的思想,对数组递归调用sort 和 merge
merge中,先建立两个临时数组分别存放mid左边和mid右边的已经排好的数列,然后合并时,有一方结束就先暂时结束,然后再检查有没有剩下的数加进去就可以了
public static void sort(int[] arr, int l, int r) { if(l < r) { int mid = l + (r - l) / 2; sort(arr, l, mid); sort(arr, mid + 1, r); merge(l, r, mid, arr); } } public static void merge(int left, int right, int mid, int[] arr) { int n1 = mid - left + 1; int n2 = right - mid; int[] L = new int[n1]; int[] R = new int[n2]; for(int i = 0; i < L.length; i++) L[i] = arr[left + i]; for(int i = 0; i < R.length; i++) R[i] = arr[mid + 1 + i]; int k = left; int i = 0, j = 0; while(i < n1 && j < n2) { if(L[i] <= R[j]){ arr[k++] = L[i++]; } else arr[k++] = R[j++]; } while(i < n1) arr[k++] = L[i++]; while(j < n2) arr[k++] = R[j++]; }
7. 基数排序
8. 堆排序 heapsort
大顶堆:是一个完全二叉树,根的值大于孩子的值,
public void sort(int arr[]) { int n = arr.length; // Build heap (rearrange array) for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // One by one extract an element from heap for (int i=n-1; i>0; i--) { // Move current root to end int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; // call max heapify on the reduced heap heapify(arr, i, 0); } } // To heapify a subtree rooted with node i which is // an index in arr[]. n is size of heap void heapify(int arr[], int n, int i) { int largest = i; // Initialize largest as root int l = 2*i + 1; // left = 2*i + 1 int r = 2*i + 2; // right = 2*i + 2 // If left child is larger than root if (l < n && arr[l] > arr[largest]) largest = l; // If right child is larger than largest so far if (r < n && arr[r] > arr[largest]) largest = r; // If largest is not root if (largest != i) { int swap = arr[i]; arr[i] = arr[largest]; arr[largest] = swap; // Recursively heapify the affected sub-tree heapify(arr, n, largest); } }