初级篇:三个O(n^2)的排序算法
仅记录代码实现和大概思路。
一、冒泡
思路:内层循环每次都从后面开始,外层从前面开始。内层每次都会找到一个小的数,放在数组的最前面。因此内层循环i
次就完成了排序。
public void BubbleSort(int[] arr){ int temp=0;//临时变量 for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。 for(int j=arr.length-1; j>i; j--){ if(arr[j] < arr[j-1]){ temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } }
二、选择排序
以如下代码为例,选择排序就是,每次都找到未排序的最小的元素,用一个变量记录这个元素索引,然后将该元素和未排序的部分的首位元素交换,可以看到交换次数只有n次。
public static void select_sort(int array[]){ for(int i=0;i<array.length-1;i++){ int minIndex = i; for(int j=i+1;j<array.length;j++){ if(array[j]<array[minIndex]){ minIndex = j; } } if(minIndex != i){ int temp = array[i]; array[i] = array[minIndex]; array[minIndex] = temp; } } }
三、插入排序
类似于打扑克牌的时候,让摸到的手牌一直有序。
public static void insert_sort(int array[]){ int temp = array[0]; for(int i=0;i<array.length-1;i++){ for(int j=i+1;j>0;j--){ if(array[j] < array[j-1]){ temp = array[j-1]; array[j-1] = array[j]; array[j] = temp; }else{ //不需要交换 提前退出是优化 break; } } } }
高级篇:三个O(nlogn)的排序算法
四、归并排序
public class MergeSort { public void MergeSort(int[] arr) { MergeSort(arr,0,arr.length-1); } private void MergeSort(int[] arr, int left, int right) { // 如果 left == right,表示数组只有一个元素,则不用递归排序 if (left < right) { // 把大的数组分隔成两个数组 int mid = (left + right) / 2; // 对左半部分进行排序 MergeSort(arr, left, mid); // 对右半部分进行排序 MergeSort(arr, mid + 1, right); //进行合并 merge(arr, left, mid, right); } } private void merge(int[] arr, int left, int mid, int right) { //先用一个临时数组把他们合并汇总起来 int[] array = new int[right - left + 1]; int i = left;//左半部分起始索引 int j = mid + 1;//右半部份起始索引 int k = 0; while (i <= mid && j <= right) { if (arr[i] < arr[j]) { array[k++] = arr[i++]; } else { array[k++] = arr[j++]; } } while(i <= mid) array[k++] = arr[i++]; while(j <= right) array[k++] = arr[j++]; // 把临时数组复制到原数组 for (i = 0; i < k; i++) { arr[left] = array[i]; left++; } } }
五、快速排序
快速排序有三个版本,下列为初级版本,版本2应该是使用随机数,版本3是三路快排,可以理解成分成三个部分,左边是小于,中间是等于,右边是大于。(暂时收录基本写法)
public class QuickSort { public static void quickSort(int[] arr) { if (arr == null || arr.length < 2) { return; } quickSort(arr, 0, arr.length - 1); } public static void quickSort(int n[], int left, int right) { int dp; if (left < right) { dp = partition(n, left, right);//先找一个数,然后分成两边处理 quickSort(n, left, dp - 1); quickSort(n, dp + 1, right); } } //partiton是最核心的部分,目的是对于某个数a,其左边都是小于a,右边都是大于a。 public static int partition(int n[], int left, int right) { int pivot = n[left];//这里选择的是最左侧,也是最基础的写法,这里使用随机数可以优化 while (left < right) { while (left < right && n[right] >= pivot) right--; if (left < right) { n[left] = n[right]; left++; } while (left < right && n[left] <= pivot) left++; if (left < right) { n[right] = n[left]; right--; } } n[left] = pivot; return left; } }
六、堆排序
堆排序的一个细节是,如果给定的是一个接一个的数据,那么慢慢插入,如果是给定了一个数组过来,则最好直接heapify调整。对应本示例的downAdjust方法。
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
public class HeapSort { // 堆排序 public static int[] heapSort(int[] arr) { int n = arr.length; //构建大顶堆 for (int i = (n - 2) / 2; i >= 0; i--) { downAdjust(arr, i, n - 1); } //进行堆排序 for (int i = n - 1; i >= 1; i--) { // 把堆顶元素与最后一个元素交换 int temp = arr[i]; arr[i] = arr[0]; arr[0] = temp; // 把打乱的堆进行调整,恢复堆的特性 downAdjust(arr, 0, i - 1); } return arr; } //下沉操作。在parent到n这个区间,parent这个位置的数不对。 public static void downAdjust(int[] arr, int parent, int n) { //临时保存要下沉的元素 int temp = arr[parent]; //定位左孩子节点的位置 int child = 2 * parent + 1; //开始下沉 while (child <= n) { // 如果右孩子节点比左孩子大,则定位到右孩子 if(child + 1 <= n && arr[child] < arr[child + 1]) child++; // 如果孩子节点小于或等于父节点,则下沉结束 if (arr[child] <= temp ) break; // 父节点进行下沉 arr[parent] = arr[child]; parent = child; child = 2 * parent + 1; } arr[parent] = temp; } }
二分查找法
public class Find { public int binarysearch(int a[], int key) { int low = 0; int high = a.length - 1; while (low <= high) { int mid = low + (high - low) / 2; if (a[mid] > key) high = mid - 1; else if (a[mid] < key) low = mid + 1; else if (a[mid] == key) return mid; } return -1; } }
又或者是
public class Find { public int binarysearch(int a[], int key) { int low = 0; int high = a.length ;//两个写法的边界是不同的 while (low < high) { int mid = low + (high - low) / 2; if (a[mid] > key) high = mid ; else if (a[mid] < key) low = mid + 1; else if (a[mid] == key) return mid; } return -1; } }