実装方法の天然ソートアルゴリズムはc++?
-
22-07-2019 - |
質問
私はソート文字列のテキストする必要がある。したいソートをソートのパーツとして数字、英数字.
例えばたい:abc1def,...,abc9def,abc10def
代わりに:abc10def,abc1def,...,abc9def
なんだろうけど、日本人アルゴリズムをここにおいて認められていることにc++)
感謝
解決
この正確な質問(Javaではありますが)と http://www.davekoelle.com/alphanum.html を指すようになりました。アルゴリズムと多くの言語での実装があります。
他のヒント
これは自然ソートとして知られています。 こちらというアルゴリズムがあります有望に見えます。
非ASCII文字の問題に注意してください( Jeffの件名のブログエントリ)。
複数の自然ソートの実装のためのC++が可能です。簡単な審査:
natural_sort<>
-に基づく効果がある。Regex.- 私の試験では、約20倍以下の選択肢としてあります。
- Dirk Jagdmannの
alnum.hpp
, に基づき、Dave Koelleの alphanumアルゴリズム- 可能性の整数overlow問題のための価値のMAXINT
- マーティンプールの
natsort
-C言語で記述され、trivially利用可能です。- のC/C++の実施などの見を大文字と小文字を区別しません、どちらかと言うと高い優先順位"自然"並べ替えができます。
- のように実装されているとは思いませんが、実際に解析小数点、それは特別な場合には先頭にゼロ(い場合は、以下のアーティストに0を仮定しているので分画)を作成が可能です。
- PHPこのアルゴリズムです。
部分的に再投稿別の回答:
bool compareNat(const std::string& a, const std::string& b){
if (a.empty())
return true;
if (b.empty())
return false;
if (std::isdigit(a[0]) && !std::isdigit(b[0]))
return true;
if (!std::isdigit(a[0]) && std::isdigit(b[0]))
return false;
if (!std::isdigit(a[0]) && !std::isdigit(b[0]))
{
if (a[0] == b[0])
return compareNat(a.substr(1), b.substr(1));
return (toUpper(a) < toUpper(b));
//toUpper() is a function to convert a std::string to uppercase.
}
// Both strings begin with digit --> parse both numbers
std::istringstream issa(a);
std::istringstream issb(b);
int ia, ib;
issa >> ia;
issb >> ib;
if (ia != ib)
return ia < ib;
// Numbers are the same --> remove numbers and recurse
std::string anew, bnew;
std::getline(issa, anew);
std::getline(issb, bnew);
return (compareNat(anew, bnew));
}
toUpper()
関数:
std::string toUpper(std::string s){
for(int i=0;i<(int)s.length();i++){s[i]=toupper(s[i]);}
return s;
}
使用法:
std::vector<std::string> str;
str.push_back("abc1def");
str.push_back("abc10def");
...
std::sort(str.begin(), str.end(), compareNat);
本質的に解析の問題であるものを状態マシンで解決するには(別名有限状態オートマトン )が道です。上記のソリューションに不満なのは、パフォーマンスの観点から上記で提案したC / C ++バリアントに勝るシンプルなワンパス早期救済アルゴリズムを作成し、数値データ型オーバーフローエラーに悩まされず、必要に応じて大文字と小文字を区別しないように簡単に変更できることです。
ソースはこちら
にあります。// -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;
}
それがあなたが望むかどうかはよくわかりませんが、とにかく、試してみることができます:-)
所属していません StackOverflow