字符串排序


字符串排序

利用字符串的特殊性质将字符串排序,比通用的排序算法效率更高

1.低位优先的字符串排序(LSD)

/**
 * 低位优先的字符串排序(LSD)
 * 概述: 适合相同长度的字符串排序,是稳定排序
 * 思想: 键索引计数法
 * 步骤: 从低位开始每轮取一个字符,使用键索引计数法排序,直到最高位结束
 */
public class LSD {
    public static void sort(String[] a,int w){
        int N = a.length;
        int R = 256;
        String[] aux = new String[N];
        int[] count = new int[R+1];
        for(int d=w-1;d>=0;d--) {//使用键索引计数法进行w轮排序
            //统计频率
            for(int i=0;i<N;++i)
                count[a[i].charAt(d)+1]++;
            //计算索引
            for(int i=0;i<R;++i)
                count[i+1] += count[i];
            //数据分类
            for(int i=0;i<N;++i)
                aux[count[a[i].charAt(d)]++] = a[i];
            //回写
            for(int i=0;i<N;++i)
                a[i] = aux[i];
            Arrays.fill(count,0);
        }
    }
}

2.高位优先的字符串排序(MSD)

/**
 * 高位优先的字符串排序(MSD)
 * 概述: 通用的字符串排序算法
 *       缺点: 对于较长相同前缀的字符串进行排序会产生大量小数组
 * 思想: 键索引计数法
 * 步骤: 使用键索引计数法每轮去一个字符从高位开始排序
 */
public class MSD {
    private static int R = 256;
    private static int M = 15;
    private static String[] aux;

    public static void sort(String[] a){
        int N = a.length;
        aux = new String[N];
        int[] count = new int[R+2];
        sort(a,0,N,0);
    }
    private static void sort(String[] a,int lo,int hi,int d){
        //if(lo >= hi-1) return;
        if (hi <= lo + M) { //较短时使用插入排序进行优化
            Insertion.sort(a, lo, hi, d);
            return;
        }
        /**
         * 键索引计数法
         */
        //统计频率
        int[] count = new int[R+2];
        for(int i=lo;i<hi;++i)
            count[charAt(a[i],d)+2]++;
        //计算索引
        for(int i=0;i<R+1;++i)
            count[i+1] += count[i];
        //数据分类
        for(int i=lo;i<hi;++i)
            aux[count[charAt(a[i],d)+1]++] = a[i];
        //回写
        for(int i=lo;i<hi;++i)
            a[i] = aux[i-lo];
        //递归:字符相同的,对下一位字符进行排序
        for(int i=0;i<R;i++)
            sort(a,lo+count[i],lo+count[i+1],d+1);
    }
    private static int charAt(String s,int d){
        if(d < s.length()) return s.charAt(d);
        return -1;
    }
}
2.1插入排序
/**
 * 插入排序
 */
public class Insertion {
    public static void sort(String[] a,int lo,int hi,int d){
        for(int i=lo+1;i<hi;++i){
            for(int j=i;j>lo && less(a[j],a[j-1],d);j--)
                exch(a,j,j-1);
        }
    }
    //比较
    private static boolean less(String a,String b,int d){
        int alen = a.length();
        int blen = b.length();
        int min = Math.min(alen,blen);
        while(d < min){
            int c1 = a.charAt(d);
            int c2 = b.charAt(d);
            if(c1 != c2) return c1 - c2 < 0;
            d++;
        }
        return alen - blen < 0;
        //return a.substring(d).compareTo(b.substring(d)) < 0;
    }
    //交换
    private static void exch(String[] a,int i,int j){
        String temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

3.三向字符串快速排序

/**
 * 三向字符串快速排序
 * 概述: 通用字符串排序算法,适合处理含有较长相同前缀的字符串
 * 步骤: 从高位开始对单个字符进行三向切分的快速排序,若按照v切分,则一轮结束后
 *       小于v部分 < 等于v部分 < 大于v部分, 对于等于v部分的下一位字符进行排序
 *       其他部分正常排序
 */
public class Quick3String {
    public static void sort(String[] a){
        sort(a,0,a.length-1,0);
    }
    private static void sort(String[] a,int lo,int hi,int d){
        if(lo >= hi) return;    //可以在较短时使用插入排序优化
        int v = charAt(a[lo],d); //取第一个为切分点,v = -1时为没有字符
        int lt = lo,gt = hi;
        int i = lt + 1;
        while(i <= gt){//从切分点下一个开始逐个归位
            int t = charAt(a[i],d);
            if(t < v) exch(a,i++,lt++); //小于v放到v左边
            else if(t > v) exch(a,i,gt--);//大于v放到右边(往末尾放)
            else i++;
        }
        // v == -1 时不会有小于v的部分,等于v的部分无需再排序
        if(v >= 0 ) sort(a,lo,lt-1,d);
        if(v >= 0 ) sort(a,lt,gt,d+1);
        sort(a,gt+1,hi,d);
    }
    //交换
    private static void exch(String[] a,int i, int j){
        String temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    private static int charAt(String s,int d){
        if(d < s.length()) return s.charAt(d);
        return -1;
    }
}

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
单词查找树 单词查找树
单词查找树 利用字符串的性质构建比通用的查找算法更有效的查找算法 1.R向单词查找树/** * R向单词查找树 * 概述: 1.每个节点都含有R个连接,对应着每个可能出现的字符 * 2.字符和键隐式的保存在数据结构中
2019-06-24
下一篇 
  目录