# 2022-04-23 字符串排序法三则

118 篇文章 4 订阅

{"ba","ac","aa","ae"}


{0, 0, 3, 4}


{"", "", "", "ba"}


{0, 0, 4, 4}


buf就变为

{"ac", "aa", "ae", "ba"}


{0, 3, 4, 4}


#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

namespace STRST
{
//字符串索引排序，用于排序有索引的字符串组
struct StrKeySort
{
explicit StrKeySort(std::istream &file)
{
}
explicit StrKeySort(const std::string &filename)
{
std::ifstream file(filename);
}

void sort()
{
for (unsigned i = 0; i != size; ++i)
{
Count[strKey[i].second + 1]++;
}
for (unsigned r = 0; r != group + 1; ++r)
{
Count[r + 1] += Count[r];
}
std::vector<std::pair<std::string, unsigned>> bufStrVec(size);
for (unsigned i = 0; i != size; ++i)
{
bufStrVec[Count[strKey[i].second]++] = strKey[i];
}
strKey = bufStrVec;
}

private:
{
std::string temp;
unsigned num = 0;
strKey.reserve(32);
Count.reserve(8);
while (file >> temp >> num)
{
strKey.emplace_back(temp, num);
++size;
if (num > group)
{
group = num;
}
}
Count = std::vector<unsigned>(group + 2, 0);
}
std::vector<std::pair<std::string, unsigned>> strKey;
std::vector<unsigned> Count;
unsigned size = 0;
unsigned group = 0;
};

//同长度字符串排序，对于同等长度字符串排序，W是字符串的长度
void lowStrSort(std::vector<std::string> &str, unsigned W)
{
unsigned vecSize = str.size();
unsigned charSize = 256;
std::vector<std::string> bufStrVec(vecSize);
for (int chOrder = static_cast<int>(W) - 1; chOrder >= 0; chOrder--)
{
std::vector<unsigned> cntTable(charSize + 1, 0);
for (int i = 0; i != vecSize; ++i)
{
cntTable[str[i].at(chOrder) + 1]++;
}
for (int r = 0; r != charSize; ++r)
{
cntTable[r + 1] += cntTable[r];
}
for (int i = 0; i != vecSize; ++i)
{
bufStrVec[cntTable[str[i].at(chOrder)]++] = str[i];
}
for (int i = 0; i != vecSize; ++i)
{
str[i] = bufStrVec[i];
}
}
}

//普通不等长字符串组排序，适合英文排序。
struct MSD
{
static void sort(std::vector<std::string> &strVec)
{
int vecSize = static_cast<int>(strVec.size());
bufStrVec = std::vector<std::string>(vecSize);
if (vecSize > 1)
{
sort(strVec, 0, vecSize - 1, 0);
}
}

private:
static const int charSize = 256;
static const int minSortSize = 15;
static std::vector<std::string> bufStrVec;
static auto charAt(const std::string &word, unsigned chOrder) -> int
{
if (chOrder < word.size())
{
return word.at(chOrder);
}
return -1;
}
static void sort(std::vector<std::string> &strVec, unsigned lo, int hi,
unsigned chOrder)
{
if (hi <= static_cast<int>(lo) + minSortSize)
{
std::sort(strVec.begin() + lo, strVec.begin() + hi + 1);
return;
}
// 建立计数表 cntTable
std::vector<unsigned> cntTable(charSize + 2);
// 将 strVec 中第 i 个字符串中 chOrder 字符对应的数值（空则为-1）+ 2
// 设以上值为 num
// 将 cntTable 中以 num 为下标的值加1.
// 如果 chOrder 字符为空, 则 cntTable[1] 的值 + 1.
for (unsigned i = lo; i != hi + 1; ++i)
{
cntTable[charAt(strVec[i], chOrder) + 2]++;
}
// strVec 中所有 string 的 chOrder 位置字母为 alpha
// cntTable 在 alpha 值 + 2 位置的值 cntTable[num] 代表 alpha 的个数
// 空字符个数在 cntTable[1] 中
// 循环累加
// 使得 cntTable[alpha + 1] 对应 alpha 在 bufStrVec 中起始位置。
for (unsigned r = 0; r != charSize + 1; ++r)
{
cntTable[r + 1] += cntTable[r];
}
// bufStrVec[num] 复制 strVec[i] 的 string
// num 是 cntTable[alphaBegin] 的值
// alphaBegin 是 strVec[i] 的 string 中 chOrder 位置字母 alpha + 1 的值
// 复制后 num 自增 1,
// 让后序相同 alpha 在 bufStrVec 中确定位置
// 最后相同 alpha 拷贝完成，num 为 bufStrVec 中最后 alpha 位置索引 +1
// 此时的 num 就是下一个 alpha 的起始位置
for (unsigned i = lo; i != hi + 1; ++i)
{
bufStrVec[cntTable[charAt(strVec[i], chOrder) + 1]++] = strVec[i];
}
// 把根据 chOrder 位置字母排序的结果，拷贝回 strVec
for (unsigned i = lo; i != hi + 1; ++i)
{
strVec[i] = bufStrVec[i - lo];
}
// 在 chOrder 处的字符已经排序完毕
// 如果 chOrder 相同字符 alpha 有多个 string 则进行 chOrder + 1
// 字符beta的排序 lo + cntTable[r] 是 alpha 在 strVec 起始位置 lo +
// cntTable[r + 1] - 1 是 alpha 在 strVec 终止位置 if 的判断条件是 alpha
// 的起始位置小于终止位置， 也就是相同 alpha 的 string 个数大于1
for (unsigned r = 0; r != charSize; ++r)
{
if (static_cast<int>(lo + cntTable[r]) <
static_cast<int>(lo + cntTable[r + 1]) - 1)
{
sort(strVec, lo + cntTable[r],
static_cast<int>(lo + cntTable[r + 1]) - 1, chOrder + 1);
}
}
}
};

std::vector<std::string> MSD::bufStrVec;

} // namespace STRST

auto main(int /*argc*/, char * /*argv*/[]) -> int
{
//  STRST::StrKeySort test("stu1.txt");
//  test.sort();
//  STRST::lowStrSort(test2, 3);
std::vector<std::string> test2{
"she",    "sells", "by",    "the", "sea",    "shore",    "tha",
"shells", "she",   "sells", "are", "surely", "seashells"};
std::vector<std::string> test3{"ab", "a"};
STRST::MSD::sort(test3);
for (const auto &i : test3)
{
std::cout << i << "\n";
}
return 0;
}


• 0
点赞
• 1
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
06-15 389
08-08 156
05-28 484
05-06 7656
03-29 523
07-10 1389
10-12 186
11-17 4361

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。