算法之排序
一、快排
public class 快速排序 { /**性质:1、时间复杂度:O(nlogn) 2、空间复杂度:O(logn) 3、非稳定排序 4、原地排序*/ public static void main(String[] args) { int[] num = {64,55,3,266,232,66,44}; quickSort(num,0,num.length-1); for (int i = 0; i < num.length; i++) { System.out.println(num[i]); } } public static int[] quickSort(int[] arr, int left, int right) { if (left < right) { //获取中轴元素所处的位置 int mid = partition(arr, left, right); //进行分割 arr = quickSort(arr, left, mid - 1); arr = quickSort(arr, mid + 1, right); } return arr; } private static int partition(int[] arr, int left, int right) { //选取中轴元素 int pivot = arr[left]; int i = left + 1; int j = right; while (true) { // 向右找到第一个小于等于 pivot 的元素位置 while (i <= j && arr[i] <= pivot) { i++; } // 向左找到第一个大于等于 pivot 的元素位置 while(i <= j && arr[j] >= pivot ){ j--; } if(i >= j) break; //交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } arr[left] = arr[j]; // 使中轴元素处于有序的位置 arr[j] = pivot; return j; } }
二、冒泡排序
public class 冒泡排序优化 { public static void main(String[] args) { int[] num = {64,65,67,66,68,69,70}; bubbleSort(num); for (int i = 0; i < num.length; i++) { System.out.println(num[i]); } } public static int[] bubbleSort(int[] arr) { if (arr == null || arr.length < 2) { return arr; } int n = arr.length; for (int i = 0; i < n; i++) { boolean flag = true; for (int j = 0; j < n -i - 1; j++) { if (arr[j + 1] < arr[j]) { flag = false; int t = arr[j]; arr[j] = arr[j+1]; arr[j+1] = t; } } //一趟下来是否发生位置交换 if(flag) break; } return arr; } }
三、选择排序
public class 选择排序 { /** * 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。 * 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法我们称之为选择排序。 * 性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序*/ public static void main(String[] args) { int[] num = {64,55,3,266,232,66,44}; selectSort(num); for (int i = 0; i < num.length; i++) { System.out.println(num[i]); } } /** * 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置 (如果第一个元素就是最小元素那么它就和自己交换)。 * 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。 如此往复,直到将整个数组排序。这种方法我们称之为选择排序。 * 性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序*/ public static int[] selectSort(int[] a) { int n = a.length; for (int i = 0; i < n - 1; i++) { int min = i; for (int j = i + 1; j < n; j++) { if(a[min] > a[j]) { min = j; } } //交换 int temp = a[i]; a[i] = a[min]; a[min] = temp; } return a; } /** 1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。 2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。 3、原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。 4、非原地排序:需要利用额外的数组来辅助排序。 5、时间复杂度:一个算法执行所消耗的时间。 6、空间复杂度:运行完一个算法所需的内存大小。 */ }
四、归并排序
public class 归并排序 { /**性质:1、时间复杂度:O(nlogn) 2、空间复杂度:O(n) 3、稳定排序 4、非原地排序*/ public static void main(String[] args) { int[] num = {64,55,3,266,232,66,44}; mergeSort(num,0,num.length-1); for (int i = 0; i < num.length; i++) { System.out.println(num[i]); } } // 归并排序 public static int[] mergeSort(int[] arr, int left, int right) { // 如果 left == right,表示数组只有一个元素,则不用递归排序 if (left < right) { // 把大的数组分隔成两个数组 int mid = (left + right) / 2; // 对左半部分进行排序 arr = mergeSort(arr, left, mid); // 对右半部分进行排序 arr = mergeSort(arr, mid + 1, right); //进行合并 merge(arr, left, mid, right); } return arr; } // 合并函数,把两个有序的数组合并起来 // arr[left..mif]表示一个数组,arr[mid+1 .. right]表示一个数组 public static void merge(int[] arr, int left, int mid, int right) { //先用一个临时数组把他们合并汇总起来 int[] a = 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]) { a[k++] = arr[i++]; } else { a[k++] = arr[j++]; } } while(i <= mid) a[k++] = arr[i++]; while(j <= right) a[k++] = arr[j++]; // 把临时数组复制到原数组 for (i = 0; i < k; i++) { arr[left++] = a[i]; } } }
程序员的眼里,不止有代码和bug,还有诗与远方和妹子!!!