0
点赞
收藏
分享

微信扫一扫

2022-04-24 三向切分字符串排序

扶摇_hyber 2022-04-24 阅读 52

接上一篇,这是将上一篇排序和快速排序结合的用于字符串排序的特殊排序法,比快排理论上要快。

上一篇的问题是当有连续重复前缀的字符串组,会不停的递归,而且会不停的产生辅助数组,当字符值范围不再是 0 - 255 而是 0 - 65535,消耗的辅助空间会过大,导致性能急速下降,作为算法的改善,将不依赖字符的映射数组,本质是快速排序再字符串这种结构的特化算法,因此极为高效。


//三向切分通用字符串排序类(英文)
struct q3StrSort
{
    //三向切分快速排序
    static void sort(std::vector<std::string> &strVec)
    {
        sort(strVec, 0, static_cast<int>(strVec.size()) - 1, 0);
    }

  private:
    //获取 word 中 chOrder 位置字符的数值
    static auto charAt(const std::string &word, int chOrder) -> int
    {
        if (chOrder < word.size())
        {
            return word.at(chOrder);
        }
        return -1;
    }
    //递归三分快速排序
    static void sort(std::vector<std::string> &strVec, int lo, int hi,
                     int chOrder)
    {
        if (hi <= lo)
        {
            return;
        }
        // 设置左边界,确定首字符串 chOrder 字符边界
        int leftNum = lo;
        // 设置右边界,确定首字符串 chOrder 字符边界
        int rightNum = hi;
        // 确定首字符串 chOrder 字符数值
        int firstChNum = charAt(strVec[lo], chOrder);
        // 设置游标,用于比较游标指向的字符串 chOrder 字符数值
        int otherNum = lo + 1;
        // 设置游标指向的字符串 chOrder 字符数值
        int otherChNum = 0;
        while (otherNum <= rightNum)
        {
            // 设置游标指向的字符串 chOrder 字符数值
            otherChNum = charAt(strVec[otherNum], chOrder);
            // 当游标指向的字符串字符小于左边界指向的字符串字符
            if (otherChNum < firstChNum)
            {
                //交换字符串,并自增游标和左边界
                std::swap(strVec[leftNum++], strVec[otherNum++]);
            }
            // 当游标指向的字符串字符大于左边界指向的字符串字符
            else if (otherChNum > firstChNum)
            {
                //交换字符串,并自减右边界
                std::swap(strVec[otherNum], strVec[rightNum--]);
            }
            // 当游标指向的字符串字符等于左边界指向的字符串字符
            else
            {
                //自增游标
                otherNum++;
            }
        }
        // strVec[lo..leftNum-1] < firstChNum = strVec[leftNum..rightNum] <
        // strVec[rightNum+1..hi]
        //递归排序左边界左侧字符串子数组
        sort(strVec, lo, leftNum - 1, chOrder);
        //如果第一字符串 chOrder 指向字符不为 -1
        if (firstChNum >= 0)
        {
            //递归排序左右边界间的字符串子数组
            sort(strVec, leftNum, rightNum, chOrder + 1);
        }
        //递归排序右边界右侧字符串子数组
        sort(strVec, rightNum + 1, hi, chOrder);
    }
};

举报

相关推荐

0 条评论