C++ 如何在c++;?
我正在对由文本和数字组成的字符串进行排序。 我希望排序将数字部分排序为数字,而不是字母数字 例如,我想要:abc1def,…,abc9def,abc10def 而不是:abc10def、abc1def、…、abc9def 有人知道这方面的算法吗(特别是在c++中)C++ 如何在c++;?,c++,sorting,natural-sort,C++,Sorting,Natural Sort,我正在对由文本和数字组成的字符串进行排序。 我希望排序将数字部分排序为数字,而不是字母数字 例如,我想要:abc1def,…,abc9def,abc10def 而不是:abc10def、abc1def、…、abc9def 有人知道这方面的算法吗(特别是在c++中) 谢谢这就是所谓的自然排序。有一种算法看起来很有前途 注意非ASCII字符的问题(请参阅主题)。我问了,并被指了指哪些字符有算法和多种语言的实现。/-1:s0s1 // -1: s0 < s1; 0: s0 == s1; 1: s
谢谢这就是所谓的自然排序。有一种算法看起来很有前途 注意非ASCII字符的问题(请参阅主题)。我问了,并被指了指哪些字符有算法和多种语言的实现。
/-1:s0s1
// -1: s0 < s1; 0: s0 == s1; 1: s0 > s1
static int numericCompare(const string &s0, const string &s1) {
size_t i = 0, j = 0;
for (; i < s0.size() && j < s1.size();) {
string t0(1, s0[i++]);
while (i < s0.size() && !(isdigit(t0[0]) ^ isdigit(s0[i]))) {
t0.push_back(s0[i++]);
}
string t1(1, s1[j++]);
while (j < s1.size() && !(isdigit(t1[0]) ^ isdigit(s1[j]))) {
t1.push_back(s1[j++]);
}
if (isdigit(t0[0]) && isdigit(t1[0])) {
size_t p0 = t0.find_first_not_of('0');
size_t p1 = t1.find_first_not_of('0');
t0 = p0 == string::npos ? "" : t0.substr(p0);
t1 = p1 == string::npos ? "" : t1.substr(p1);
if (t0.size() != t1.size()) {
return t0.size() < t1.size() ? -1 : 1;
}
}
if (t0 != t1) {
return t0 < t1 ? -1 : 1;
}
}
return i == s0.size() && j == s1.size() ? 0 : i != s0.size() ? 1 : -1;
}
静态整数比较(常量字符串和s0、常量字符串和s1){
尺寸i=0,j=0;
对于(;i
<>我不太确定如果你想要,无论如何,你可以试试:-< /P> < P>几种C++的自然排序实现。简要回顾:
- -基于Boost.Regex。
- 在我的测试中,它大约比其他选项慢20倍
- 德克·贾格德曼的,基于戴夫·科勒的
- MAXINT上的值可能存在整数超限问题
< List> Martin PoCH,用C编写,但C++使用简单。
- 我见过的唯一一个C/C++实现提供了不区分大小写的版本,这似乎是“自然”排序的一个高优先级
- 与其他实现一样,它实际上并不解析小数点,但它会解析特殊情况下的前导零(前导0的任何内容都假定为分数),这有点奇怪,但可能很有用
- PHP使用这个算法
std::vector<std::string> str;
str.push_back("abc1def");
str.push_back("abc10def");
...
std::sort(str.begin(), str.end(), compareNat);
std::vector str;
str.push_back(“abc1def”);
str.push_back(“abc10def”);
...
std::sort(str.begin()、str.end()、compareNat);
要解决本质上的解析问题,状态机(aka)是一条出路。由于对上述解决方案不满意,我编写了一个简单的单通早期纾困算法,该算法在性能方面优于上面建议的C/C++变体,不会出现数字数据类型溢出错误,并且很容易修改,以便在需要时添加大小写不敏感
可以找到源文件对于那些到达这里并且已经在其项目中使用Qt的人,您可以使用
QCollator
类。有关详细信息,请参阅。雪崩排序是自然排序的递归变体,在探索排序数据堆栈时,合并运行。算法运行/排序时,即使将数据添加到排序堆中,算法也将保持排序稳定
搜索原理很简单仅合并具有相同等级的运行。
找到前两个naturell跑步(排名0)后,AvalanchSort将它们合并为排名1的跑步。然后它调用雪崩排序,生成第二个排名为1的运行,并将两个运行合并为排名为2的运行。然后它调用雪崩排序,在未排序的数据上生成秩为2的运行
我的实现使用接口注入将排序与数据处理分开。您可以对数组、关联数组或列表等数据结构使用该算法
/**
* @param DataListAvalancheSortInterface $dataList
* @param DataRangeInterface $beginRange
* @param int $avalancheIndex
* @return bool
*/
public function startAvalancheSort(DataListAvalancheSortInterface $dataList)
{
$avalancheIndex = 0;
$rangeResult = $this->avalancheSort($dataList, $dataList->getFirstIdent(), $avalancheIndex);
if (!$dataList->isLastIdent($rangeResult->getStop())) {
do {
$avalancheIndex++;
$lastIdent = $rangeResult->getStop();
if ($dataList->isLastIdent($lastIdent)) {
$rangeResult = new $this->rangeClass();
$rangeResult->setStart($dataList->getFirstIdent());
$rangeResult->setStop($dataList->getLastIdent());
break;
}
$nextIdent = $dataList->getNextIdent($lastIdent);
$rangeFollow = $this->avalancheSort($dataList, $nextIdent, $avalancheIndex);
$rangeResult = $this->mergeAvalanche($dataList, $rangeResult, $rangeFollow);
} while (true);
}
return $rangeResult;
}
/**
* @param DataListAvalancheSortInterface $dataList
* @param DataRangeInterface $range
* @return DataRangeInterface
*/
protected function findRun(DataListAvalancheSortInterface $dataList,
$startIdent)
{
$result = new $this->rangeClass();
$result->setStart($startIdent);
$result->setStop($startIdent);
do {
if ($dataList->isLastIdent($result->getStop())) {
break;
}
$nextIdent = $dataList->getNextIdent($result->getStop());
if ($dataList->oddLowerEqualThanEven(
$dataList->getDataItem($result->getStop()),
$dataList->getDataItem($nextIdent)
)) {
$result->setStop($nextIdent);
} else {
break;
}
} while (true);
return $result;
}
/**
* @param DataListAvalancheSortInterface $dataList
* @param $beginIdent
* @param int $avalancheIndex
* @return DataRangeInterface|mixed
*/
protected function avalancheSort(DataListAvalancheSortInterface $dataList,
$beginIdent,
int $avalancheIndex = 0)
{
if ($avalancheIndex === 0) {
$rangeFirst = $this->findRun($dataList, $beginIdent);
if ($dataList->isLastIdent($rangeFirst->getStop())) {
// it is the last run
$rangeResult = $rangeFirst;
} else {
$nextIdent = $dataList->getNextIdent($rangeFirst->getStop());
$rangeSecond = $this->findRun($dataList, $nextIdent);
$rangeResult = $this->mergeAvalanche($dataList, $rangeFirst, $rangeSecond);
}
} else {
$rangeFirst = $this->avalancheSort($dataList,
$beginIdent,
($avalancheIndex - 1)
);
if ($dataList->isLastIdent($rangeFirst->getStop())) {
$rangeResult = $rangeFirst;
} else {
$nextIdent = $dataList->getNextIdent($rangeFirst->getStop());
$rangeSecond = $this->avalancheSort($dataList,
$nextIdent,
($avalancheIndex - 1)
);
$rangeResult = $this->mergeAvalanche($dataList, $rangeFirst, $rangeSecond);
}
}
return $rangeResult;
}
protected function mergeAvalanche(DataListAvalancheSortInterface $dataList, $oddListRange, $evenListRange)
{
$resultRange = new $this->rangeClass();
$oddNextIdent = $oddListRange->getStart();
$oddStopIdent = $oddListRange->getStop();
$evenNextIdent = $evenListRange->getStart();
$evenStopIdent = $evenListRange->getStop();
$dataList->initNewListPart($oddListRange, $evenListRange);
do {
if ($dataList->oddLowerEqualThanEven(
$dataList->getDataItem($oddNextIdent),
$dataList->getDataItem($evenNextIdent)
)) {
$dataList->addListPart($oddNextIdent);
if ($oddNextIdent === $oddStopIdent) {
$restTail = $evenNextIdent;
$stopTail = $evenStopIdent;
break;
}
$oddNextIdent = $dataList->getNextIdent($oddNextIdent);
} else {
$dataList->addListPart($evenNextIdent);
if ($evenNextIdent === $evenStopIdent) {
$restTail = $oddNextIdent;
$stopTail = $oddStopIdent;
break;
}
$evenNextIdent = $dataList->getNextIdent($evenNextIdent);
}
} while (true);
while ($stopTail !== $restTail) {
$dataList->addListPart($restTail);
$restTail = $dataList->getNextIdent($restTail);
}
$dataList->addListPart($restTail);
$dataList->cascadeDataListChange($resultRange);
return $resultRange;
}
}查看“相关”侧栏…@dmckee-公平地说,他没有使用“自然排序”这个词(我问同样的问题时也没有使用)这是后来编辑的。那很好,但是我没有提升的能力:-看起来Paul Tomblin的答案可能对你更有帮助——C++变体似乎没有什么有用的东西。+ 1谢谢保罗。我寻找自然排序和C++标签,但是没有找到任何东西。这个返回0用于代码>数字比较(“Z01”,“Z1”)< /代码>,这个算法使用额外的内存:临时字符串。至少,你可以使用范围(迭代器对)来代替。这不是很有效,一个更有效和全面的解决方案是请将你的代码发布在这里,而不是让他们访问你的个人网站。我的个人网站是维护它的地方,它将在哪里。很高兴我能帮助别人。
std::vector<std::string> str;
str.push_back("abc1def");
str.push_back("abc10def");
...
std::sort(str.begin(), str.end(), compareNat);
/**
* @param DataListAvalancheSortInterface $dataList
* @param DataRangeInterface $beginRange
* @param int $avalancheIndex
* @return bool
*/
public function startAvalancheSort(DataListAvalancheSortInterface $dataList)
{
$avalancheIndex = 0;
$rangeResult = $this->avalancheSort($dataList, $dataList->getFirstIdent(), $avalancheIndex);
if (!$dataList->isLastIdent($rangeResult->getStop())) {
do {
$avalancheIndex++;
$lastIdent = $rangeResult->getStop();
if ($dataList->isLastIdent($lastIdent)) {
$rangeResult = new $this->rangeClass();
$rangeResult->setStart($dataList->getFirstIdent());
$rangeResult->setStop($dataList->getLastIdent());
break;
}
$nextIdent = $dataList->getNextIdent($lastIdent);
$rangeFollow = $this->avalancheSort($dataList, $nextIdent, $avalancheIndex);
$rangeResult = $this->mergeAvalanche($dataList, $rangeResult, $rangeFollow);
} while (true);
}
return $rangeResult;
}
/**
* @param DataListAvalancheSortInterface $dataList
* @param DataRangeInterface $range
* @return DataRangeInterface
*/
protected function findRun(DataListAvalancheSortInterface $dataList,
$startIdent)
{
$result = new $this->rangeClass();
$result->setStart($startIdent);
$result->setStop($startIdent);
do {
if ($dataList->isLastIdent($result->getStop())) {
break;
}
$nextIdent = $dataList->getNextIdent($result->getStop());
if ($dataList->oddLowerEqualThanEven(
$dataList->getDataItem($result->getStop()),
$dataList->getDataItem($nextIdent)
)) {
$result->setStop($nextIdent);
} else {
break;
}
} while (true);
return $result;
}
/**
* @param DataListAvalancheSortInterface $dataList
* @param $beginIdent
* @param int $avalancheIndex
* @return DataRangeInterface|mixed
*/
protected function avalancheSort(DataListAvalancheSortInterface $dataList,
$beginIdent,
int $avalancheIndex = 0)
{
if ($avalancheIndex === 0) {
$rangeFirst = $this->findRun($dataList, $beginIdent);
if ($dataList->isLastIdent($rangeFirst->getStop())) {
// it is the last run
$rangeResult = $rangeFirst;
} else {
$nextIdent = $dataList->getNextIdent($rangeFirst->getStop());
$rangeSecond = $this->findRun($dataList, $nextIdent);
$rangeResult = $this->mergeAvalanche($dataList, $rangeFirst, $rangeSecond);
}
} else {
$rangeFirst = $this->avalancheSort($dataList,
$beginIdent,
($avalancheIndex - 1)
);
if ($dataList->isLastIdent($rangeFirst->getStop())) {
$rangeResult = $rangeFirst;
} else {
$nextIdent = $dataList->getNextIdent($rangeFirst->getStop());
$rangeSecond = $this->avalancheSort($dataList,
$nextIdent,
($avalancheIndex - 1)
);
$rangeResult = $this->mergeAvalanche($dataList, $rangeFirst, $rangeSecond);
}
}
return $rangeResult;
}
protected function mergeAvalanche(DataListAvalancheSortInterface $dataList, $oddListRange, $evenListRange)
{
$resultRange = new $this->rangeClass();
$oddNextIdent = $oddListRange->getStart();
$oddStopIdent = $oddListRange->getStop();
$evenNextIdent = $evenListRange->getStart();
$evenStopIdent = $evenListRange->getStop();
$dataList->initNewListPart($oddListRange, $evenListRange);
do {
if ($dataList->oddLowerEqualThanEven(
$dataList->getDataItem($oddNextIdent),
$dataList->getDataItem($evenNextIdent)
)) {
$dataList->addListPart($oddNextIdent);
if ($oddNextIdent === $oddStopIdent) {
$restTail = $evenNextIdent;
$stopTail = $evenStopIdent;
break;
}
$oddNextIdent = $dataList->getNextIdent($oddNextIdent);
} else {
$dataList->addListPart($evenNextIdent);
if ($evenNextIdent === $evenStopIdent) {
$restTail = $oddNextIdent;
$stopTail = $oddStopIdent;
break;
}
$evenNextIdent = $dataList->getNextIdent($evenNextIdent);
}
} while (true);
while ($stopTail !== $restTail) {
$dataList->addListPart($restTail);
$restTail = $dataList->getNextIdent($restTail);
}
$dataList->addListPart($restTail);
$dataList->cascadeDataListChange($resultRange);
return $resultRange;
}