当前位置:   article > 正文

算法:排序 二叉树深度时间复杂度? 归并和快速排序实践?B树时间复杂度?_二叉树排序的复杂度

二叉树排序的复杂度

概念:以某个值或值的集合为输入,将输入转换成输出的计算步骤的一个序列。

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)

  1. public static void merge(int[] a, int low, int mid, int high) {
  2. int[] temp = new int[high - low + 1];
  3. System.out.println("temp:" + Arrays.toString(temp));
  4. int i = low;// 左指针
  5. int j = mid + 1;// 右指针
  6. int k = 0;
  7. // 把较小的数先移到新数组中
  8. while (i <= mid && j <= high) {
  9. if (a[i] < a[j]) {
  10. temp[k++] = a[i++];
  11. System.out.println("把较小的数先移到新数组中1:" + Arrays.toString(temp));
  12. System.out.println("k:"+k);
  13. } else {
  14. temp[k++] = a[j++];
  15. System.out.println("把较小的数先移到新数组中2:" + Arrays.toString(temp));
  16. System.out.println("k:"+k);
  17. }
  18. }
  19. // 把左边剩余的数移入数组
  20. while (i <= mid) {
  21. temp[k++] = a[i++];
  22. System.out.println("把左边剩余的数移入数组:" + Arrays.toString(temp));
  23. }
  24. // 把右边边剩余的数移入数组
  25. System.out.println("j:"+j);
  26. while (j <= high) {
  27. temp[k++] = a[j++];
  28. System.out.println("把右边边剩余的数移入数组:" + Arrays.toString(temp));
  29. }
  30. // 把新数组中的数覆盖nums数组
  31. for (int k2 = 0; k2 < temp.length; k2++) {
  32. a[k2 + low] = temp[k2];
  33. }
  34. }
  35. public static void mergeSort(int[] a, int low, int high) {
  36. int mid = (low + high) / 2;
  37. if (low < high) {
  38. // 左边
  39. mergeSort(a, low, mid);
  40. // 右边
  41. mergeSort(a, mid + 1, high);
  42. // 左右归并
  43. merge(a, low, mid, high);
  44. System.out.println(Arrays.toString(a));
  45. }
  46. }
  47. public static void main(String[] args) {
  48. int a[] = { 51, 46, 20, 18};
  49. mergeSort(a, 0, a.length - 1);
  50. System.out.println("排序结果:" + Arrays.toString(a));
  51. }
  1. 一.其实就是数学里的必用习惯:直接表示法。
  2. 1.将原始问题原子性得表达为不可再拆解得独立子问题,一一映射到逻辑步骤里。(有几个子问题就有几个步骤)
  3. 2.把用到的不同含义的变量(此题只把循环用到的表示出来了)独立表示出来如左边数组的第一位最后一位,右边数组的第一位最后一位
  4. package test.MainTEST;
  5. import java.util.Arrays;
  6. import static test.MainTEST.TestRunTimeSelfException.INSTANCEOne;
  7. public class MainTest {
  8. public static void main(String[] args) {
  9. //测试是否能捕获throw
  10. MainTest main = new MainTest();
  11. //System.out.println(INSTANCEOne.getCode());
  12. /*归并排序*/
  13. int[] a = {54,52,30, 20,10,5,98,67,69};
  14. int length = a.length;
  15. main.merge(a, 0, length / 2 - 1, length / 2, length - 1, length);
  16. System.out.println("结果数组" + Arrays.toString(a));
  17. }
  18. private int[] merge(int[] a, int leftFirst, int leftLast, int rightFirst, int rightLast, int len) {
  19. int[] temp = new int[len];
  20. if (len == 1) {
  21. return a;
  22. }
  23. int leftLen = leftLast - leftFirst + 1;
  24. if(leftLen>=2) {
  25. //子左分割,归并
  26. int sonLeftLast = leftFirst + leftLen/2 -1;
  27. int sonrightFirst = sonLeftLast + 1;
  28. this.merge(a, leftFirst, sonLeftLast, sonrightFirst, leftLast, leftLen);
  29. }
  30. int rightLen = len - leftLen;
  31. if(rightLen>=2){
  32. //子右分割,归并
  33. int sonLeftLast = rightFirst + rightLen / 2 - 1;
  34. int sonrightFirst = sonLeftLast + 1;
  35. this.merge(a, rightFirst, sonLeftLast, sonrightFirst, rightLast, rightLen);
  36. }
  37. //归并最外层
  38. int i = leftFirst,j=rightFirst,k=0;
  39. while (i <= leftLast & j <= rightLast)
  40. {
  41. if (a[i] <= a[j]) {
  42. temp[k++] = a[i++];
  43. } else {
  44. temp[k++] = a[j++];
  45. }
  46. }
  47. //左边剩余的处理(此时右边刚好处理完)
  48. while (i <= leftLast)
  49. {
  50. temp[k++] = a[i++];
  51. }
  52. //右边的剩余处理(此时左边刚好处理完)
  53. while (j <= rightLast)
  54. {
  55. temp[k++] = a[j++];
  56. }
  57. for (int m = 0; m < temp.length; m++) {
  58. a[leftFirst++] = temp[m];
  59. }
  60. System.out.println("temp数组:"+Arrays.toString(temp));
  61. System.out.println("每归并一次:" + Arrays.toString(a));
  62. return a;
  63. }
  64. }

快速排序

 

 

二叉树的时间复杂度

平衡二叉排序树深度为Log2|n+1,时间复杂度为O(Log2|n)

如果二叉排序树完全不平衡,则二叉排序树的深度为n,退化为顺序查找,时间复杂度为O(n)。

综上,二叉排序树的时间复杂度介于O(Log2|n)和O(n)之间。因此为了提高查询效率,二叉排序树最好构造成平衡的。

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/681211
推荐阅读
相关标签
  

闽ICP备14008679号