赞
踩
概念:以某个值或值的集合为输入,将输入转换成输出的计算步骤的一个序列。
O(1)<O(logn)<O(n)<O(nlogn)<O(n*n)
算法的时间复杂度用来衡量随问题规模n的增长执行次数的增长率。
常见排序:
插入排序
遍历数组,遍历到i时,a0,a1...ai-1是已经排好序的,取出ai,从ai-1开始从后向前和每个比较大小(从前向后比的话需要考虑移动其他元素的问题),如果小于,则将此位置元素向后移动,继续先前比较,如果不小于,则放到正在比较的元素之后。可见相等元素比较是,原来靠后的还是拍在后边,所以插入排序是稳定的。
冒泡排序
冒泡排序的名字很形象,实际实现是相邻两节点进行比较,大的向后移一个,经过第一轮两两比较和移动,最大的元素移动到了最后,第二轮次大的位于倒数第二个,依次进行。这是最基本的冒泡排序,还可以进行一些优化。
优化一:如果某一轮两两比较中没有任何元素交换,这说明已经都排好序了,算法结束,可以使用一个Flag做标记,默认为false,如果发生交互则置为true,每轮结束时检测Flag,如果为true则继续,如果为false则返回。
优化二:某一轮结束位置为j,但是这一轮的最后一次交换发生在lastSwap的位置,则lastSwap到j之间是排好序的,下一轮的结束点就不必是j--了,而直接到lastSwap即可,代码如下:
归并排序
时间复杂度O(nlogn)
public static void merge(int[] a, int low, int mid, int high) { int[] temp = new int[high - low + 1]; System.out.println("temp:" + Arrays.toString(temp)); int i = low;// 左指针 int j = mid + 1;// 右指针 int k = 0; // 把较小的数先移到新数组中 while (i <= mid && j <= high) { if (a[i] < a[j]) { temp[k++] = a[i++]; System.out.println("把较小的数先移到新数组中1:" + Arrays.toString(temp)); System.out.println("k:"+k); } else { temp[k++] = a[j++]; System.out.println("把较小的数先移到新数组中2:" + Arrays.toString(temp)); System.out.println("k:"+k); } } // 把左边剩余的数移入数组 while (i <= mid) { temp[k++] = a[i++]; System.out.println("把左边剩余的数移入数组:" + Arrays.toString(temp)); } // 把右边边剩余的数移入数组 System.out.println("j:"+j); while (j <= high) { temp[k++] = a[j++]; System.out.println("把右边边剩余的数移入数组:" + Arrays.toString(temp)); } // 把新数组中的数覆盖nums数组 for (int k2 = 0; k2 < temp.length; k2++) { a[k2 + low] = temp[k2]; } } public static void mergeSort(int[] a, int low, int high) { int mid = (low + high) / 2; if (low < high) { // 左边 mergeSort(a, low, mid); // 右边 mergeSort(a, mid + 1, high); // 左右归并 merge(a, low, mid, high); System.out.println(Arrays.toString(a)); } } public static void main(String[] args) { int a[] = { 51, 46, 20, 18}; mergeSort(a, 0, a.length - 1); System.out.println("排序结果:" + Arrays.toString(a)); }
一.其实就是数学里的必用习惯:直接表示法。 1.将原始问题原子性得表达为不可再拆解得独立子问题,一一映射到逻辑步骤里。(有几个子问题就有几个步骤) 2.把用到的不同含义的变量(此题只把循环用到的表示出来了)独立表示出来如左边数组的第一位最后一位,右边数组的第一位最后一位 package test.MainTEST; import java.util.Arrays; import static test.MainTEST.TestRunTimeSelfException.INSTANCEOne; public class MainTest { public static void main(String[] args) { //测试是否能捕获throw MainTest main = new MainTest(); //System.out.println(INSTANCEOne.getCode()); /*归并排序*/ int[] a = {54,52,30, 20,10,5,98,67,69}; int length = a.length; main.merge(a, 0, length / 2 - 1, length / 2, length - 1, length); System.out.println("结果数组" + Arrays.toString(a)); } private int[] merge(int[] a, int leftFirst, int leftLast, int rightFirst, int rightLast, int len) { int[] temp = new int[len]; if (len == 1) { return a; } int leftLen = leftLast - leftFirst + 1; if(leftLen>=2) { //子左分割,归并 int sonLeftLast = leftFirst + leftLen/2 -1; int sonrightFirst = sonLeftLast + 1; this.merge(a, leftFirst, sonLeftLast, sonrightFirst, leftLast, leftLen); } int rightLen = len - leftLen; if(rightLen>=2){ //子右分割,归并 int sonLeftLast = rightFirst + rightLen / 2 - 1; int sonrightFirst = sonLeftLast + 1; this.merge(a, rightFirst, sonLeftLast, sonrightFirst, rightLast, rightLen); } //归并最外层 int i = leftFirst,j=rightFirst,k=0; while (i <= leftLast & j <= rightLast) { if (a[i] <= a[j]) { temp[k++] = a[i++]; } else { temp[k++] = a[j++]; } } //左边剩余的处理(此时右边刚好处理完) while (i <= leftLast) { temp[k++] = a[i++]; } //右边的剩余处理(此时左边刚好处理完) while (j <= rightLast) { temp[k++] = a[j++]; } for (int m = 0; m < temp.length; m++) { a[leftFirst++] = temp[m]; } System.out.println("temp数组:"+Arrays.toString(temp)); System.out.println("每归并一次:" + Arrays.toString(a)); return a; } }
快速排序
二叉树的时间复杂度
平衡二叉排序树深度为Log2|n+1,时间复杂度为O(Log2|n)
如果二叉排序树完全不平衡,则二叉排序树的深度为n,退化为顺序查找,时间复杂度为O(n)。
综上,二叉排序树的时间复杂度介于O(Log2|n)和O(n)之间。因此为了提高查询效率,二叉排序树最好构造成平衡的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。