zoukankan      html  css  js  c++  java
  • 《算法》第五章部分程序 part 2

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(计数 + 插排),(原地排序),(三路快排,与前面的三路归并排序相同)

    ● 计数 + 插排

      1 package package01;
      2 
      3 import edu.princeton.cs.algs4.StdIn;
      4 import edu.princeton.cs.algs4.StdOut;
      5 
      6 public class class01
      7 {
      8     private static final int BITS_PER_BYTE = 8;
      9     private static final int BITS_PER_INT = 32;
     10     private static final int R = 256;
     11     private static final int CUTOFF = 15;   // 尺寸不超过 CUTOFF 的数组使用插入排序
     12 
     13     private class01() {}
     14 
     15     public static void sort(String[] a)     // 对字符串的排序
     16     {
     17         int n = a.length;
     18         String[] aux = new String[n];
     19         sortKernel(a, 0, n - 1, 0, aux);
     20     }
     21 
     22     private static void sortKernel(String[] a, int lo, int hi, int d, String[] aux)
     23     {
     24         if (hi <= lo + CUTOFF)              // 数组较小,使用插入排序
     25         {
     26             insertion(a, lo, hi, d);
     27             return;
     28         }
     29         int[] count = new int[R + 2];
     30         for (int i = lo; i <= hi; i++)
     31             count[charAt(a[i], d) + 2]++;
     32         for (int r = 0; r < R + 1; r++)
     33             count[r + 1] += count[r];
     34         for (int i = lo; i <= hi; i++)
     35             aux[count[charAt(a[i], d) + 1]++] = a[i];
     36         for (int i = lo; i <= hi; i++)      // 写回时注意偏移
     37             a[i] = aux[i - lo];
     38         for (int r = 0; r < R; r++)         // 每个字母开头的子数组分别排序
     39             sortKernel(a, lo + count[r], lo + count[r + 1] - 1, d + 1, aux);
     40     }
     41 
     42     private static void insertion(String[] a, int lo, int hi, int d)    // 数组 a 关于第 d 位插入排序
     43     {
     44         for (int i = lo; i <= hi; i++)
     45         {
     46             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
     47                 exch(a, j, j - 1);
     48         }
     49     }
     50 
     51     private static void exch(String[] a, int i, int j)
     52     {
     53         String temp = a[i];
     54         a[i] = a[j];
     55         a[j] = temp;
     56     }
     57 
     58     private static int charAt(String s, int d)              // 按索引取字符串的字符
     59     {
     60         assert d >= 0 && d <= s.length();
     61         if (d == s.length())
     62             return -1;
     63         return s.charAt(d);
     64     }
     65 
     66     private static boolean less(String v, String w, int d)
     67     {
     68         //assert v.substring(0, d).equals(w.substring(0, d)); // 先检查等于
     69         for (int i = d; i < Math.min(v.length(), w.length()); i++)
     70         {
     71             if (v.charAt(i) < w.charAt(i))
     72                 return true;
     73             if (v.charAt(i) > w.charAt(i))
     74                 return false;
     75         }
     76         return v.length() < w.length();
     77     }
     78 
     79     public static void sort(int[] a)        // 对数组的排序
     80     {
     81         int n = a.length;
     82         int[] aux = new int[n];
     83         sortKernel(a, 0, n - 1, 0, aux);
     84     }
     85 
     86     private static void sortKernel(int[] a, int lo, int hi, int d, int[] aux)
     87     {
     88         if (hi <= lo + CUTOFF)
     89         {
     90             insertion(a, lo, hi, d);
     91             return;
     92         }
     93         int[] count = new int[R + 1];
     94         int mask = R - 1;
     95         int shift = BITS_PER_INT - BITS_PER_BYTE * d - BITS_PER_BYTE;
     96         for (int i = lo; i <= hi; i++)
     97         {
     98             int c = (a[i] >> shift) & mask;
     99             count[c + 1]++;
    100         }
    101         for (int r = 0; r < R; r++)
    102             count[r + 1] += count[r];
    103         if (d == 0)                         // 符号位,0x00-0x7F 要排在 0x80-0xFF 的后面
    104         {
    105             int shift1 = count[R] - count[R / 2];
    106             int shift2 = count[R / 2];
    107             for (int r = 0; r < R / 2; r++)
    108                 count[r] += shift1;
    109             for (int r = R / 2; r < R; r++)
    110                 count[r] -= shift2;
    111         }
    112         for (int i = lo; i <= hi; i++)
    113         {
    114             int c = (a[i] >> shift) & mask;
    115             aux[count[c]++] = a[i];
    116         }
    117         for (int i = lo; i <= hi; i++)
    118             a[i] = aux[i - lo];
    119         if (d == 4)                         // 已经到了最高位,不用分治了
    120             return;
    121         if (count[0] > 0)
    122             sortKernel(a, lo, lo + count[0] - 1, d + 1, aux);
    123         for (int r = 0; r < R; r++)
    124         {
    125             if (count[r + 1] > count[r])    // 存在数字第 d 位是 r 的数字需要排序
    126                 sortKernel(a, lo + count[r], lo + count[r + 1] - 1, d + 1, aux);
    127         }
    128     }
    129 
    130     private static void insertion(int[] a, int lo, int hi, int d)
    131     {
    132         for (int i = lo; i <= hi; i++)
    133         {
    134             for (int j = i; j > lo && a[j] < a[j - 1]; j--)
    135                 exch(a, j, j - 1);
    136         }
    137     }
    138 
    139     private static void exch(int[] a, int i, int j)
    140     {
    141         int temp = a[i];
    142         a[i] = a[j];
    143         a[j] = temp;
    144     }
    145 
    146     public static void main(String[] args)
    147     {
    148         String[] a = StdIn.readAllStrings();
    149         int n = a.length;
    150         sort(a);
    151         for (int i = 0; i < n; i++)
    152             StdOut.println(a[i]);
    153     }
    154 }

    ● 原地排序

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.StdIn;
     4 import edu.princeton.cs.algs4.StdOut;
     5 
     6 public class class01
     7 {
     8     private static final int R = 256;
     9     private static final int CUTOFF = 0;
    10 
    11     private class01() {}
    12 
    13     public static void sort(String[] a)
    14     {
    15         int n = a.length;
    16         sortKernel(a, 0, n - 1, 0);
    17     }
    18 
    19     private static void sortKernel(String[] a, int lo, int hi, int d)
    20     {
    21         if (hi <= lo + CUTOFF)
    22         {
    23             insertion(a, lo, hi, d);
    24             return;
    25         }
    26         int[] heads = new int[R + 2];       // 需要记录每个字符出现的首位和末位
    27         int[] tails = new int[R + 1];
    28         for (int i = lo; i <= hi; i++)
    29             heads[charAt(a[i], d) + 2]++;
    30         heads[0] = lo;                      // heads 首位设为 lo,方便直接做 a 的索引
    31         for (int r = 0; r < R + 1; r++)
    32         {
    33             heads[r + 1] += heads[r];
    34             tails[r] = heads[r + 1];        // tails 等于前缀和的 heads 左移一格,等于下一个字符出现的位置
    35         }
    36         for (int r = 0; r < R + 1; r++)     // 循环完成所有字符
    37         {
    38             for (; heads[r] < tails[r]; heads[r]++)     // 循环直到所有 heads 向 tails 靠拢
    39             {
    40                 // a[heads[r]] 作为临时位置,每次把其上字符串发送到排序后正确的位置上,替换下来的字符串放回,用于下一次发送
    41                 for (int c = charAt(a[heads[r]], d); c + 1 != r; c = charAt(a[heads[r]], d))
    42                     exch(a, heads[r], heads[c + 1]++);  // 每次发送后要后移同一字符串的目标位置
    43             }
    44         }
    45         for (int r = 0; r < R; r++)                     // 分治所有子数组
    46             sortKernel(a, tails[r], tails[r + 1] - 1, d + 1);
    47     }
    48 
    49     private static void insertion(String[] a, int lo, int hi, int d)
    50     {
    51         for (int i = lo; i <= hi; i++)
    52         {
    53             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
    54                 exch(a, j, j - 1);
    55         }
    56     }
    57 
    58     private static void exch(String[] a, int i, int j)
    59     {
    60         String temp = a[i];
    61         a[i] = a[j];
    62         a[j] = temp;
    63     }
    64 
    65     private static int charAt(String s, int d)
    66     {
    67         assert d >= 0 && d <= s.length();
    68         if (d == s.length())
    69             return -1;
    70         return s.charAt(d);
    71     }
    72 
    73     private static boolean less(String v, String w, int d)
    74     {
    75         // assert v.substring(0, d).equals(w.substring(0, d));
    76         for (int i = d; i < Math.min(v.length(), w.length()); i++)
    77         {
    78             if (v.charAt(i) < w.charAt(i))
    79                 return true;
    80             if (v.charAt(i) > w.charAt(i))
    81                 return false;
    82         }
    83         return v.length() < w.length();
    84     }
    85 
    86     public static void main(String[] args)
    87     {
    88         String[] a = StdIn.readAllStrings();
    89         int n = a.length;
    90         sort(a);
    91         for (int i = 0; i < n; i++)
    92             StdOut.println(a[i]);
    93     }
    94 }

    ● 三路快排

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.StdIn;
     4 import edu.princeton.cs.algs4.StdOut;
     5 import edu.princeton.cs.algs4.StdRandom;
     6 
     7 public class class01
     8 {
     9     private static final int CUTOFF = 15;
    10 
    11     private class01() {}
    12 
    13     public static void sort(String[] a)
    14     {
    15         StdRandom.shuffle(a);
    16         sortKernel(a, 0, a.length - 1, 0);
    17     }
    18 
    19     private static void sortKernel(String[] a, int lo, int hi, int d)
    20     {
    21         if (hi <= lo + CUTOFF)
    22         {
    23             insertion(a, lo, hi, d);
    24             return;
    25         }
    26         int lt = lo, gt = hi;
    27         int v = charAt(a[lo], d);
    28         for (int i = lo + 1; i <= gt;)
    29         {
    30             int t = charAt(a[i], d);
    31             if (t < v)
    32                 exch(a, lt++, i++);
    33             else if (t > v)
    34                 exch(a, i, gt--);
    35             else
    36                 i++;
    37         }
    38         sortKernel(a, lo, lt - 1, d);
    39         if (v >= 0)
    40             sortKernel(a, lt, gt, d + 1);
    41         sortKernel(a, gt + 1, hi, d);
    42     }
    43 
    44     private static void insertion(String[] a, int lo, int hi, int d)
    45     {
    46         for (int i = lo; i <= hi; i++)
    47         {
    48             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
    49                 exch(a, j, j - 1);
    50         }
    51     }
    52 
    53     private static boolean less(String v, String w, int d)
    54     {
    55         assert v.substring(0, d).equals(w.substring(0, d));
    56         for (int i = d; i < Math.min(v.length(), w.length()); i++)
    57         {
    58             if (v.charAt(i) < w.charAt(i))
    59                 return true;
    60             if (v.charAt(i) > w.charAt(i))
    61                 return false;
    62         }
    63         return v.length() < w.length();
    64     }
    65 
    66     private static int charAt(String s, int d)
    67     {
    68         assert d >= 0 && d <= s.length();
    69         if (d == s.length())
    70             return -1;
    71         return s.charAt(d);
    72     }
    73 
    74     private static void exch(String[] a, int i, int j)
    75     {
    76         String temp = a[i];
    77         a[i] = a[j];
    78         a[j] = temp;
    79     }
    80 
    81     public static void main(String[] args)
    82     {
    83         String[] a = StdIn.readAllStrings();
    84         int n = a.length;
    85 
    86         sort(a);
    87 
    88         for (int i = 0; i < n; i++)
    89             StdOut.println(a[i]);
    90     }
    91 }
  • 相关阅读:
    Python类属性的延迟计算
    解析Python编程中的包结构
    解析Python编程中的包结构
    Python查询Mysql时返回字典结构的代码
    VS2010中如何查看DLL的导出接口
    C++ 简单的日志类
    ilmerge工具合并多个DLL或EXE
    基于InstallShield2013LimitedEdition的安装包制作
    c# 操作注册表
    Source Insight 常用设置和快捷键大全
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9869261.html
Copyright © 2011-2022 走看看