算法系列—高位优先的字符串排序

《算法第四版第五章》
在高位优先的字符串排序算法中,要特别注意到达字符串末尾的情况。合理的做法是将 所有字符都已经被检查过的字符串 排在 所有子数组的前面。
高位优先排序对于待排序的字符串没有什么要求
高位优先排序的过程中使用了键索引计数算法
高位优先排序要特别注意字符串达到末尾的情况,因为当字符串达到末尾时,比其本身加上任意字符都要小,如app小于apple。为了判断字符串是否已达到末尾的情况,编写字符索引函数int charAt(const string& str, int d),当字符索引大于字符长度即字符串达到结尾时,返回-1,否则返回索引字符对应的ASCII码。


如下三张图可帮助理解:

算法系列—高位优先的字符串排序_第1张图片







C++代码如下:

#include
#include
#include 
#include 

const int R = 256;	//字母表基数
const int M = 0;	//小数组的切换阈值
using namespace std;

int charAt(const string& str, int d)	//返回字符串str下标为d的字符,如果超出字符串长度则返回-1
{
	if (d < str.size())
		return str[d];
	else
		return -1;
}
//参数分别表示,字符串容器,排序字符串开始位置,排序字符串结束位置,以第几个字符为键,辅助存储容器
void MSD_sort(vector& sVec, int lo, int hi, int d,vector& aux)
{
	if (hi <= lo + M) {
		//Insert_sort(sVec, lo, hi, d);
		return;
	}
	int count[R + 2] = { 0 };
	//计算频率
	for (int i = lo; i <= hi; i++)
	{
		count[charAt(sVec[i], d) + 2]++;
	}
	//将频率转换为索引
	for (int r = 0; r < R + 1; r++)
	{
		count[r + 1] += count[r];
	}
	//分类
	for (int i = lo; i <= hi; i++)
	{
		aux[count[charAt(sVec[i],d)+1]++] = sVec[i];
	}
	//回写
	for (int i = lo; i <= hi; i++)
	{
		sVec[i] = aux[i - lo];
	}

	//递归的以每个字符为键进行排序
	for (int r = 0; r < R; r++)
	{
		MSD_sort(sVec, lo + count[r], lo + count[r + 1] - 1, d + 1, aux);
	}
}

int main()
{
	string str;
	vector sVec;
	sVec.push_back("huangpangpang");
	sVec.push_back("suanfa");
	sVec.push_back("diwuzhang");
	sVec.push_back("msdsort");
	sVec.push_back("huangpang");

	int n = sVec.size();
	vector aux(n);
	MSD_sort(sVec, 0, n - 1, 0, aux);
	for (vector::iterator it = sVec.begin(); it < sVec.end(); it++)
	{
		cout << *it << endl;
	}
}

3.大幅度提升性能的方法

在数值排序中提到过一次优化排序效率的方法:当待排序数组的长度较小时,使用插入排序。同样的,该方法也适应与高位优先字符串排序,而且这种优化一般情况下也是必须的,有专家做过实验,在数据量巨大时,将长度小于10的子数组排序切换到插入排序,可以将排序的效率提升十倍左右。

针对字符串的插入排序和数值的插入排序思想一模一样,上述代码的这一行去掉注释,修改M的大小(即剩多少字符就开始插入排序)。

//Insert_sort(sVec, lo, hi, d);

具体代码如下:

void insertion_sort(vector<string>& sVec, int lo, int hi, int d)
{
    for (int i=lo+1; i<=hi; i++)
        for (int j=i; j>lo && charAt(sVec[j], d)1], d); j--) 
        {
            string temp = sVec[j];
            sVec[j] = sVec[j-1];
            sVec[j-1] = temp;
        }
}


你可能感兴趣的:(数据结构与算法)