如何使用 std::sort 按特定顺序对字符串进行排序
how to use std::sort to sort strings in a particular order
我在我的一个项目中遇到了这种情况,我需要根据给定字符的顺序对字符串进行排序。
所以理想情况下,这是我的要求。
假设我的初始字母顺序是b,B,A,a,d,c,C,D,T,t。
我有 3 根字符串"Bat"
、"bat"
、"atb"
。排序后,数组应根据上述给定顺序"bat"
、"Bat"
、"atb"
b < B < a
。
所以我正在考虑使用std::sort
的 c++。
但我不确定这整个想法。如果想法很好,可以使用什么数据结构来存储字母的初始顺序以及如何编写排序的比较函数。
sort(arr, arr + 3, compare);
bool compare(string a, string b)
{
/*how to proceed here?
}
有没有其他方法可以比使用std::sort
更有效?
任何想法都会有所帮助。
自定义比较器和std::sort
应该足以满足您的操作。比较器的重要部分是确保它遵循严格的弱排序。该排序的属性之一是:
给定 a 和 b,如果
(!(a < b || b < a))
为真,则 a 和 b 必须是等价的。
将自定义比较器构造为函子非常简单,是存储字母表的好地方。为了避免即使具有排序logN效率的字符串扫描,也可以使用包含数字排序顺序等价的自定义字母表。这将非常快,对于大型字符串比较尤其出色,因为每个字符查找都是恒定时间。
自定义比较器示例如下:
#include <iostream>
#include <algorithm>
#include <string>
#include <climits>
struct CustomAlphaCmp
{
int table[1 << CHAR_BIT];
CustomAlphaCmp(const std::string& alpha)
{
std::fill(std::begin(table), std::end(table), INT_MAX);
int value = 0;
for (auto x : alpha)
table[ static_cast<unsigned char>(x) ] = ++value;
}
bool operator()(const std::string& a, const std::string& b)
{
auto lhs = a.begin();
auto rhs = b.begin();
for (; lhs != a.end() && rhs != b.end(); ++lhs,++rhs)
{
int lhs_val = table[static_cast<unsigned char>(*lhs)];
int rhs_val = table[static_cast<unsigned char>(*rhs)];
if (lhs_val != rhs_val)
return lhs_val < rhs_val;
}
return (rhs != b.end());
}
};
int main()
{
std::string alpha = "bBAadcCDTt";
std::string ar[] = { "Bat", "bat", "X", "atb", "bBb", "bbb", "B",
"bat", "aaa", "Y", "Cat", "CaT", "Bat", "A" };
std::sort(std::begin(ar), std::end(ar), CustomAlphaCmp(alpha));
for (auto const& s : ar)
std::cout << s << 'n';
}
输出
bbb
bBb
bat
bat
B
Bat
Bat
A
aaa
atb
CaT
Cat
Y
X
工作原理
比较器对象是从自定义字母表构造的,以使用字母表位置作为表中的"值"来初始化所有可能的char
值的表索引。所有非字母字符的值都为 INT_MAX
,为它们提供"最弱"的可能顺序值,并将它们全部视为等效。
完成后,比较器将移交给排序算法。比较两个字符串时,将遍历它们,直到遇到不匹配的值或一个/两个字符串达到终止。此时,要么字符串同时完成,要么左边"完成",要么右边先完成。我们知道到目前为止的所有字符都是平等的。因此,如果左边先于右边完成,那么只有这样,左边才真正"小于"右边。如果它们是相同的,或者右侧首先完成(不是哪个重要),则左侧不能少。因此,我们可以简单地返回右侧是否到达其终点作为最终答案。
此特定比较器忽略所有非字母字符,因此任何字母字符都将小于任何非字母字符,并且所有非字母字符都被视为相等。如果这还不足以满足您的需求,则可能需要进行一些调整。
最后,比较器的准备时间是固定的填充成本加上字母长度的O(n)。如果您在许多排序操作中使用相同的字母表,请提前准备比较器并将其发送到std::sort
可能是必要的。同样,可能需要根据您的需要进行一些调整。
无论如何,祝你好运。
这是一种自定义排序比较运算符的方法
struct comparisonFuction
{
inline bool operator() (const YourCustomClass& obj1, const YourCustomClass& obj2)
{
return (obj1.customValue < obj2.customValue);
}
};
std::vector < YourCustomClass > vec;
std::sort(vec.begin(), vec.end(), comparisonFuction());
- 按字母顺序对字符串中的字母进行排序,而无需使用内置的 sort()
- 按字母顺序对C++问题中的子字符串索引进行分区
- 提高从排序字符串中获取字母顺序的顺序复杂性
- 字符串变量顺序
- 高效的字符串截断算法,按顺序删除相等的前缀和后缀
- 反转字符串中单词的位置,而不更改 O(1) 空格限制中特殊字符的顺序
- C++按字母顺序排列的字符串数组
- 如何在 c++ 中按字母顺序排列数组中的字符串?
- C++ 按数值对元组<字符串、浮点数>然后按字典顺序排序的向量
- 如何根据长度然后字母顺序对数组字符串进行排序?
- C 在向量的向量中按字母顺序排序字符串
- ODBC:如何将空字符串绑定到C 中的空
- 将字符串值分配给Char数组以相反的顺序进行循环
- 检索字符串的第一个字符,并在C++中按字母顺序进行比较
- 将字符指针按顺序存储在 map 中 std::map<char*, int> mymap。将其存储为字符或字符串不是一个选项
- 添加字符串和文字,顺序如何影响是否可以正确添加字符串
- 我不知道如何创建一个以数字/字母顺序打印出我的整数或字符串的程序
- 加速变体:绑定顺序中是否有魔力
- 颠倒字符串的顺序
- OpenGL VBO 绑定顺序