• [Algorithm Basics] Sorting, LinkedList


    Time complexity:

    Binary search O(log2 n):

    i=0.   n elements:         -------------------

    i=1.   n/2 elements:                   ----------

    i=2.   n/4 elements:                          -----

    ...

    i=i.    n/2^i elements:                        -

    进行n/2^i=1, i=log2 n 次,来达到只剩一个element.

    1,Selection Sort

    Steps:

    from 0~n-1, select the minimum element[comparing n-1 times], swap it with the A[0].

    from 1~n-1, select the minimum element[comparing n-2 times], swap it with the A[1].

    ...

    So total comparison times: n-1+n-2+...+2+1 = n(n-1)/2=O(n^2).

    2, Insertion Sort

    Steps:

    i, compare with j=0~i-1=0, if bigger than A[j], nothing changes; if smaller than A[j], A[j+1] = A[j], move A[i] to position j.

    So total comparison times:  1+2+...+n-1=n(n-1)/2=O(n^2).

    3, Merge 2 sorted arrays

    像两叠放着的纸牌,最上面放着最小的牌,指针从上开始往下,注意的是两叠的高度不同,一叠到底以后只需考虑另一叠。

    4, Bubble Sort

    也是两层loop, 比较相邻两个element,如果前面大于后面,就swap,这样每一轮把最大的那个扔到末端。

    public static void sort(int[] a) {

      for(int i = 0; i< a.length; i++) {

        for(int j = 0; j<a.length -1 - i; j++) {
          if(a[j] > a[j+1]) {
            int temp = a[j];
            a[j]= a[j+1];
            a[j+1] = temp;
        }}}
    }

    5, Quick Sort

    Divide and Conquer, Recuisive, Complexity: O(nlogn), worst-case: O(n^2)[if you pick the pivot which is the biggest/smallest value in the array].

    private static void quickSort2(int[] array, int low, int high) {
      int i = low, j= high;
      int mid = (low + high) /2;
      while(i<=j) {
        while(array[i] < array[mid]) i++;
        while(array[j] > array[mid]) j--;
        if(i<= j) {
          int temp = array[i];
          array[i] = array[j];
          array[j] = temp;
          i++;  //Don't forget to increase/decrease index here
          j--;
        }
      }
      if(low < j) quickSort2(array, low, j);
      if(i < high) quickSort2(array, i, high);
    }

     6, Merge Sort 

    Worst-case and average are both: O(nlogn). 每层都比较n次,有logn层。

    Use helplerArray to copy from, One method for divide and conquer, One method for merging lower part and higher part.

    private void mergeSort(int low, int high) {
      if(low<high) {
        int middle = (low + high)/2;
        mergeSort(low, middle);
        mergeSort(middle +1, high);
        merge(low, middle, high);
      }
    }
    private void merge(int low, int middle, int high) {
      for(int i = low; i<= high; i++)
        helper[i] = this.numbers[i];
      int i = low;            //pointer i for low part of helper array
      int j = middle + 1;  //pointer j for higher part of helper array
      int k = low;           //pointer k for target array
      while(i<= middle && j<= high) {
        if(helper[i] < helper[j]) numbers[k++] = helper[i++];
        else numbers[k++] = helper[j++];
      }
      while(j<=high) numbers[k++] = helper[j++];
      while(i<=middle) numbers[k++] = helper[i++];
    }

    Steps: 1, private var int[] numbers, int[] helper; 2, private method mergeSort(int low, int high), 在这里做recursion,先mergeSort(low, mid)再mergeSort(mid+1, high); 3, private method merge(int low, int mid, int high),在这里先把low~high赋给helper array,然后开始比较.

    7, Radix Sort O(n)

    Radix Sort puts the elements in order by comparing the digits of the numbers. We should start sorting by comparing and ordering the one's digits:Now, we gather the sublists (in order from the 0 sublist to the 9 sublist) into the main list again:the sublists are created again, this time based on the ten's digit:Finally, the sublists are created according to the hundred's digit.

    In the example above, the numbers were all of equal length, but many times, this is not the case. If the numbers are not of the same length, then a test is needed to check for additional digits that need sorting. This can be one of the slowest parts of Radix Sort, and it is one of the hardest to make efficient.

    时间复杂度O(n*k),k是位数。k不一定小于logn。

    Java program:

    func(int[] arr, int maxDigits)

    int exp = 1;

    for(int i = 0; i<maxDigits; i++) {

      ArrayList[] bucketList = new ArrayList[10]; //use ArrayList<ArrayList<Integer>>.

      for(int k = 0; k<10; k++)  bucketList[k] = new ArrayList();

      for(int j = 0; j< arr.length; j++) { int index = arr[j]/exp%10; bucketList[index].add(arr[j]);

      exp = exp *10;

      int number = 0;

      for(int k = 0; k<10; k++) {//循环bucketList将所有element回放到原arr中}

    }

    8, Count Sort

    原数组A={3, 5, 6, 3, 3, 5};

    统计组B={0, 0, 0, 3, 0, 2, 1}; => {0, 0, 0, 0, 3, 3, 3, 5};  //数组B的长度是k, B[A[i]]++; for(i:k){oldCount = B[i]; B[i]=total; total+=oldCount;}

    排序组C={3, 3, 3, 5, 5, 6}       //C[B[A[i]]=A[i]; B[A[i]]++;

    Count Sort对于数组的元素值范围比较小,频率比较大的情况有效。时间和空间复杂度都是O(n+k)。和Radix sort一样,都不是比较排序。计数排序是用来排序0到100之间的数字的最好的算法。

    9, Arrays.sort()

    用的是Dual-pivot quick sort, average and worst time complexity are O(nlogn), worst我不确定,document里说的是对于多数情况下比quick sort要好。

    Collections.sort(List<T> list); 的不同之处在于它是sort List, 据说内部是将list转成array用同样的排序算法,complexity is also O(nlogn).

    Linked List

    先构建一个Node:

    class Node{

      int num;

      Node next;

      public Node(int n) { num = n; next = null;}

    }

    基本的构建一个singly linked list:

    public static void main(String[] args) {
      Node top = null, node = null, last = null;
      System.out.printf("Enter some integers ending with 0 ");
      Scanner in = new Scanner(System.in);
      int input = in.nextInt();
      while(input != 0) {
        top = addInPlace(top, input);  
        input = in.nextInt();
      }
      print(top);
    }

    构建sorted linked list的方法:

    public static Node addInPlace(Node top, int input) {
      Node prev = null;
      Node curr = top;
      Node node = new Node(input);
      while(curr != null && input > curr.num) {
        prev = curr;
        curr = curr.next;
      }
      node.next = curr;
      if(prev == null) return node;
      prev.next = node;
      return top;
    }

    Insert node into a circular sorted linked list的方法:

    public static void insertIntoCircularList(Node top, int key) {
      Node curr = top;
      Node prev = null;
      Node node = new Node(key);
      do{
        prev = curr;
        curr = curr.next;
        if(key > prev.num && key <curr.num) break;
        if(key < prev.num && key <curr.num) break;
      }while(curr!= top);
      prev.next = node;
      node.next = curr;
    }

    反转singly linked list的方法:

    private static Node reverseList(Node top) {
      Node p1 = null;
      Node p2 = top;
      Node p3 = null;
      while(p2 != null) {
        p3 = p2.next;
        p2.next = p1;
        p1 = p2;
        p2 = p3;
      }
      return p1;
    }

    asd

  • 相关阅读:
    Entity Framework Code First 模式-建立一对一联系
    Entity Framework Code First 模式-建立一对多联系
    sqllocaldb
    NuGet 命令行使用EntityFrameWork
    c# 中反射里的invoke方法的参数
    在js中使用Razor
    一个页面上调用多个setInterval失效解决办法(使用于同一时间间隔)
    Echart使用过的属性总结
    VS注释与取消注释快捷键
    hibernate的强转类型
  • 原文地址:https://www.cnblogs.com/chayu3/p/3928167.html
Copyright © 2020-2023  润新知