zoukankan      html  css  js  c++  java
  • Sorting Algorithms Overview

      Time Complexity of an algorithm is usually estimated as the asymptotic number of elementary operations with respect to an input size. When it comes to comparison-based sorting algorithms, the so-called elementary operation is usually referred to the comparison of key values.

    1. Comparison-Based Sorting Algorithms

      Comparison-based sorting algorithms have a lower bound of time complexity as O(n*log n). Here I shall provide a Java program involving following sorting algorithms:
      (1)  Selection Sort:  unstable and of quadratic time complexity

      (2)  Insertion Sort:  stable and of quadratic time complexity

      (3)  Binary Insertion Sort:  stable and of O(n*log n) time complexity in terms of comparisons

      (4)  Quick Sort:  unstable and of O(n*log n) average time as long as pivot is randomly chosen

      (5)  Merge Sort:  stable and of O(n*log n) worst-case time complexity

      (6)  Heap Sort:  unstable and of O(n*log n) worst-case time complexity

      1 class Array<T extends Comparable> {
      2     private T[] items;        // data of array items
      3     private int len;            // current length
      4     private int size;           // size of space
      5     
      6     public Array(int size) {
      7         if (size<=0) {
      8             throw new RuntimeException("Illegal Initial Size");
      9         } else {
     10             this.size = size;
     11             items = (T[]) new Comparable[size];
     12         }
     13     }
     14     public void append(T item) {
     15         // Insert a new item in items[len]
     16         if (len==size) {
     17             doubleSize();
     18         }
     19         items[len++] = item;
     20     }
     21     private void doubleSize() {
     22         // Double the space size when it's filled up
     23         if ((size<<1)<0) {
     24             throw new RuntimeException("Size Expansion Failed");
     25         } else {
     26             T[] tmp = items;
     27             items = (T[]) new Comparable[size<<1];
     28             for (int i=0;i<len;i++) {
     29                 items[i] = tmp[i];
     30             }
     31             size <<= 1;
     32         }
     33     }
     34     public void selectSort() {
     35         // Implement Selection Sort Algorithm
     36         for (int i=0;i<len-1;i++) {
     37             int idx = i;
     38             T key = items[idx];
     39             for (int j=i+1;j<len;j++) {
     40                 if (items[j].compareTo(key)<0) {
     41                     idx = j;
     42                     key = items[idx];
     43                 }
     44             }
     45             items[idx] = items[i];
     46             items[i] = key;
     47         }
     48     }
     49     public void insertSort() {
     50         // Implement Insertion Sort Algorithm
     51         for (int i=1;i<len;i++) {
     52             T key = items[i];
     53             int j = i-1;
     54             for (;j>=0&&items[j].compareTo(key)>0;j--) {
     55                 items[j+1] = items[j];
     56             }
     57             items[j+1] = key;
     58         }
     59     }
     60     public void binInsSort() {
     61         // Implement Binary Insertion Sort
     62         for (int i=1;i<len;i++) {
     63             T key = items[i];
     64             int pos = binSrch(0,i-1,key);
     65             for (int j=i;j>pos;j--) {
     66                 items[j] = items[j-1];
     67             }
     68             items[pos] = key;
     69         }
     70     }
     71     private int binSrch(int p,int r,T key) {
     72         //   Search for the position to insert key in itmes[p...r]
     73         //   Precondition:        items[p...r] is a sorted array
     74         //   Postcondition:    the position of  the least item larger than
     75         //               key in items[p...r] if it exists, otherwise return r+1
     76         if (p==r)  {
     77             if (items[p].compareTo(key)<=0) {
     78                 return p+1;
     79             } else {
     80                 return p;
     81             }
     82         } else  {
     83             int q = (p+r)/2;
     84             if (items[q+1].compareTo(key)>0) {
     85                 return binSrch(p,q,key);
     86             } else {
     87                 return binSrch(q+1,r,key);
     88             }
     89         }
     90     }
     91     public void quickSort() {
     92         //    Implement Quick Sort Algorithm
     93         genRandPerm();
     94         qsort(0,len-1);
     95     }
     96     private void genRandPerm() {
     97         // Perturb items into a random permutation
     98         Random rand = new Random();
     99         for (int i=0;i<len-1;i++) {
    100             int idx = i+rand.nextInt(len-i);
    101             T tmp = items[idx];
    102             items[idx] = items[i];
    103             items[i] = tmp;
    104         }
    105     }
    106     private void qsort(int p,int r) {
    107         // Divide & Conquer for quick sort
    108         if (p<r) {
    109             int q = partition(p,r);
    110             qsort(p,q-1);
    111             qsort(q+1,r);
    112         }
    113     }
    114     private int partition(int p,int r) {
    115         // Partition items[p...r] for qsort procedure
    116         //  Precondition:        items[p...r] is a random permutation
    117         //  Postcondition:    items[q+1...r] are larger than items[q]
    118         //        items[p...q-1] are smaller than or equal to items[q]
    119         //        pivot index q is returned
    120         T key = items[r];
    121         int i = p-1;
    122         for (int j=p;j<r;j++) {
    123             //    Loop Invariant:    items[i...j-1] are larger than key
    124             //          items[p...i-1] are smaller than or equal to key
    125             if (items[j].compareTo(key)<=0) {
    126                 i = i+1;
    127                 T tmp = items[i];
    128                 items[i] = items[j];
    129                 items[j] = tmp;
    130             }
    131         }
    132         items[r] = items[i+1];
    133         items[i+1] = key;
    134         return i+1;
    135     }
    136     public void mergeSort() {
    137         // Implement Merge Sort Algorithm
    138         T[] tmp = (T[]) new Comparable[len];
    139         msort(tmp,0,len-1);
    140     }
    141     private void msort(T[] tmp,int p,int r) {
    142         // Divide & Conquer for merge sort
    143         if (p<r) {
    144             int q = ((p+r)>>1);
    145             msort(tmp,p,q);
    146             msort(tmp,q+1,r);
    147             merge(tmp,p,q,r);
    148         }
    149     }
    150     private void merge(T[] tmp,int p,int q,int r) {
    151         // Merge items[p...q] and items[q+1...r] into a whole
    152         //  Precondition:        items[p...q] and items[q+1....r] are sorted
    153         //  Postcondition:    items[p...r] is sorted
    154         for (int i=p;i<=r;i++) {
    155             tmp[i] = items[i];
    156         }
    157         int i = p, j = q+1, k = p;
    158         while (i<=q&&j<=r)  {
    159             //    both left[] and right[] haven't run out
    160             if (tmp[i].compareTo(tmp[j])<0) {
    161                 items[k++] = tmp[i++];
    162             } else {
    163                 items[k++] = tmp[j++];
    164             }
    165         }
    166         while (i<=q) {
    167             // only left[] hasn't run out
    168             items[k++] = tmp[i++];
    169         }
    170         while (j<=r) {
    171             // only right[] hasn't run out
    172             items[k++] = tmp[j++];
    173         }
    174     }
    175     public void heapsort() {
    176         // Implement Heap Sort Algorithm
    177         for (int i=((len-3)>>1);i>=0;i--) {
    178             // build a max-heap
    179             sift_down(len,i);
    180         }
    181         int n = len;
    182         for (int i=len-1;i>0;i--) {
    183             // extract the max item
    184             T tmp = items[0];
    185             items[0] = items[i];
    186             items[i] = tmp;
    187             sift_down(--n,0);
    188         }
    189     }
    190     public void sift_down(int n,int i) {
    191         // MAX_HEAPIFY from items[i] given n is the heap size
    192         int j = (i<<1)+1, k = (i<<1)+2, idx = i;
    193         if (j<n) {
    194             if (items[idx].compareTo(items[j])<0) {
    195                 idx = j;
    196             }
    197             if (k<n&&items[idx].compareTo(items[k])<0) {
    198                 idx = k;
    199             }
    200             if (idx>i) {
    201                 T tmp = items[i];
    202                 items[i] = items[idx];
    203                 items[idx] = tmp;
    204                 sift_down(n,idx);
    205             }
    206         }
    207     }
    208     public void display() {
    209         // Display the array items on the console
    210         if (len>0) {
    211             System.out.print(items[0]);
    212             for (int i=1;i<len;i++) {
    213                 System.out.print(" "+items[i]);
    214             }
    215         }
    216         System.out.println();
    217     }
    218     
    219 }

    2. Counting Sort

      Since Counting Sort is not based on comparisons, its time complexity has no lower bound as those mentioned above. As an integer sorting algorithm, counting sort takes O(N) time, where N is the range of the input integers (MAX - MIN).

      Talk is cheap, show you my code.  ╮( ̄. ̄)╭

     1     public static void countSort(int[] arr) {
     2         int n = arr.length;
     3                 int min = arr[0], max = arr[0];
     4         for (int i=1;i<n;i++) {
     5             // Determine the minimum and maximum values
     6             if (min>arr[i]) {
     7                 min = arr[i];
     8             } else if (max<arr[i]){
     9                 max = arr[i];
    10             }
    11         }
    12         max -= min;
    13         int[] cnt = new int[max+1];
    14         for (int i=0;i<n;i++) {
    15             // Count the frequency of each value in arr[]
    16             cnt[arr[i]-min]++;
    17         }
    18         for (int i=1;i<=max;i++) {
    19             // Determine the starting position of each value
    20             cnt[i] += cnt[i-1];
    21         }
    22         int pos = 0;
    23         for (int i=0;i<=max;i++) {
    24             // Put the values in their proper positions
    25             while (cnt[i]>pos) {
    26                 arr[pos++] = i+min;
    27             }
    28         }
    29     }

    3. Applications of Sorting Algorithms

      We can apply the sorting algorithms described above to many other problems. For instance, we can select a certain Order Statistic of an integer array by drawing on the partition method in Quick Sort:

     1     public static int select(int[] arr,int idx) {
     2         // Determine the idxth Order Statistic in arr[]
     3         // Precondition: 1<=idx<=arr.length
     4         // Postcondition: the value desired is returned
     5         int n = arr.length;
     6         int[] tmp = new int[n];
     7         for (int i=0;i<n;i++) {
     8             tmp[i] = arr[i];
     9         }
    10         return selectHelp(tmp,0,n-1,idx);
    11     }
    12     private static int selectHelp(int[] arr,int p,int r,int idx) {
    13         // Determine the idxth Order Statistic among arr[p...r]
    14         // Precondition: 1<=idx<=r+1-p (p<=r)
    15         // Postcondition: the value desired is returned
    16         if (p==r) {
    17             return arr[p];
    18         } 
    19         int key = arr[r];
    20         int q = p;
    21         for (int j=p;j<r;j++) {
    22             // arr[p...q-1]<=key<arr[q...j]
    23             if (arr[j]<=key) {
    24                 int tmp = arr[q];
    25                 arr[q] = arr[j];
    26                 arr[j] = tmp;
    27                 q++;
    28             }
    29         }
    30         arr[r] = arr[q];
    31         arr[q] = key;
    32         if (idx<=q-p) {
    33             return selectHelp(arr,p,q-1,idx);
    34         } else {
    35             return selectHelp(arr,q,r,idx+p-q);
    36         }
    37     }

      Another example is that we use the merge method in Merge Sort to count the number of inversions in a given integer array:

     1     public static int invNum(int[] arr) {
     2         int n = arr.length;
     3         int[] tmp = new int[n];
     4         for (int i=0;i<n;i++) {
     5             tmp[i] = arr[i];
     6         }
     7         int[] left = new int[(n-1)/2+2];
     8         int[] right = new int[n/2+1];
     9         return invNumHelp(tmp,0,n-1,left,right);
    10     }
    11     private static int invNumHelp(int[] arr,int p,int r,int[] left,int[] right) {
    12         // Determine the number of inversions in arr[p...r]
    13         //        and meanwhile turn it into increasing order
    14         if (p==r) {
    15             return 0;
    16         } 
    17         int q = ((p+r)>>1), val = 0;
    18         // solve subproblems recursively
    19         val += invNumHelp(arr,p,q,left,right);
    20         val += invNumHelp(arr,q+1,r,left,right);
    21         // copy arr[] to left[] and right[]
    22         for (int i=p;i<=q;i++) {
    23             left[i-p] = arr[i];
    24         }
    25         for (int i=q+1;i<=r;i++) {
    26             right[i-q-1] = arr[i];
    27         }
    28         // set sentinels in left[] and right[]
    29         left[q+1-p] = (1<<31)-1;
    30         right[r-q] = (1<<31)-1;
    31         // count inversions across left and right
    32         for (int i=0,j=0,k=p;k<=r;k++) {
    33             if (left[i]>right[j]) {
    34                 arr[k] = right[j++];
    35                 val += (q+1-p-i);
    36             } else {
    37                 arr[k] = left[i++];
    38             }
    39         }
    40         return val;
    41     }

      As a matter of fact, Quick Sort is a Divide-and-Conquer Algorithm that solves the problem in a top-down way, while Merge Sort adopts a bottom-up approach instead.


    References:

      1. Cormen, T. H. et al. Introduction to Algorithms [M] .  北京:机械工业出版社, 2006-09



  • 相关阅读:
    对文件上传使用表单验证
    文件上传
    自定义验证器
    WTForms常用的验证器
    Eclipse自动补全+常用快捷键
    JNI笔记
    cocos2d 2.2.6 win7下的配置
    cocos2d 3.6 win7下的配置
    python--文件删除、判断目录存在、字符串替换
    只是一个文件节点类为了项目的数据处理
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4415428.html
Copyright © 2011-2022 走看看