常见的排序算法
1.二分查找算法
public int search(int[] args, int num) { int start = 0; int end = args.length - 1; while (start <= end) { int mid = start + (end-start) / 2; if (num < args[mid]) { end = mid - 1; } if (num > args[mid]) { start = mid + 1; } if (num == args[mid]) { return mid; } } return -1; }
2.常见的排序算法 如果相同元素的相对次序不发生改变,那这种排序方式是稳定的排序方式
2.1.冒泡排序:时间复杂度为:O(n2) ,
原理:依次比较两个相邻的元素,将值大的元素交换到后面;这样每一趟就把最大的值放在了最后,然后下一趟对剩余的元素进行比较,直到数组有序;
算法分析:N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数
public static void sort(int[] args) { int temp = 0; // 标记每趟是否发生变化 boolean flag = false; for (int i = 0; i < args.length - 1; i++) { // 注意这里,下边要进行加1,为防止数组越界要减1 for (int j = 0; j < args.length - i - 1; j++) { // 如果前面的数比后面的数大,则进行交换 if (args[j] > args[j + 1]) { temp = args[j]; args[j] = args[j + 1]; args[j + 1] = temp; flag = true; } } if (!flag) { return; } } }
2.2.直接选择排序 时间复杂度为:O(n2)
算法思想:首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置;接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。以此类推,直到 所有元素均排序完毕。
public static void sort(int[] arg) { for (int i = 0; i < arg.length - 1; i++) { // 假定每趟开始的最小元素为未排序的第一个元素 int minIndex = i; for (int j = i + 1; j < arg.length; j++) { // 如果存在元素比当前最小元素要小; if (arg[minIndex] > arg[j]) { minIndex = j; } } if (minIndex != i) { int temp = arg[i]; arg[i] = arg[minIndex]; arg[minIndex] = temp; } } }
2.3.插入排序 时间复杂度为:O(n2)
算法思想:将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话, n个元素需要进行n-1趟排序。
public static void sort(int[] arg) { for (int i = 0; i < arg.length; i++) { if (arg[i] < arg[i - 1]) { int j; // 待插入的数 int current = arg[i]; // 从有序表中的最后一个元素开始进行比较 // current < arr[j],说明待插入元素小于有序表中的j元素, // 就需要将arr[j]元素后移; for (j = i - 1; j >= 0 && current < arg[j]; j--) { arg[j + 1] = arg[j]; } arg[j + 1] = current; } } }
2.4.希尔排序 时间复杂度为:O(nlogn)
算法思想:对于n个待排序的数列,取一个小于n的整数gap=n/2(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入 排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap=gap/2的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。
public static void sort(int[] arg) { System.out.println(Arrays.toString(arg)); for (int step = arg.length / 2; step > 0; step = step / 2) { // 每组进行直接插入排序 for (int i = step; i < arg.length; i++) { int current = arg[i]; int j; for (j = i - step; j >= 0 && current < arg[j]; j -= step) { arg[j + step] = arg[j]; } arg[j + step] = current; } // 一次分组后的排序结果 System.out.println(Arrays.toString(arg)); } }
2.5.快速排序 时间复杂度O(nlogn)
算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归 进 行,以此达到整个数据变成有序序列。
public static void sort(int[] arg, int left, int right) { System.out.println(Arrays.toString(arg)); System.out.println("left=" + left + ", right=" + right); int lt = left; int rt = right; // pivot 是中轴值 int pivot = arg[(left + right) / 2]; // 循环让比pivot小的值放在左边,比pivot大的值放在右边 while (lt < rt) { // 在pivot的左边一直找,直到找到一个比pivot大的值 while (arg[lt] < pivot) { lt++; } // 在pivot的右边边一直找,直到找到一个比pivot小的值 while (arg[rt] > pivot) { rt--; } // 表示pivot的左边已经是全部小于等于pivot;pivot的右边已经是大于等于pivot if (lt >= rt) { break; } // 左右两边进行交换 int temp = arg[lt]; arg[lt] = arg[rt]; arg[rt] = temp; // 交换完成后如果发现lt处的值等于pivot,则rt减1; if (arg[lt] == pivot) { rt--; } // 交换完成后如果发现rt处的值等于pivot,则lt加1; if (arg[rt] == pivot) { lt++; } } // 如果lt==rt,则必须进行加减; if (lt == rt) { lt++; rt--; } if (left < rt) { sort(arg, left, rt); } if (right > lt) { sort(arg, lt, right); } }