我的目标是根据两个标准对单词列表进行排序:
例如:
{red,a,three,b,four,aeoli}
应排序为:
{a,b,red,four,aeoli,three}.
我有两个单独的快速排序:一个是长度,后面是一个按字母顺序排列。
我只是好奇如何合并这两个? 我遇到的主要问题是我不知道如何按照字母顺序排序,同时考虑到长度,并贯穿整个列表。
感谢任何建议,以下代码是我的主要功能和快速排序功能:
Vector<String> words;
String word;
ifstream inFile;
inFile.open("practice.txt");
while(!inFile.eof()){
getLine(inFile,word);
words.push_back(word);
}
inFile.close();
String pivot = "qog";
if(words[2] < pivot)
cout << "Bigger" << endl;
words.quicksort(2,words.length()-2);
words.quicksort2(2,words.length()-2);
快速排序长度
template <typename T>
void Vector<T>::quicksort(int left, int right)
{
int i = left;
int j = right;
String pivot = data[(left+right)/2];
if(i <= j)
{
while(data[i].getLength() < pivot.getLength())
i++;
while(pivot.getLength() < data[j].getLength())
j--;
}
if(i <= j)
{
String temp = data[i];
data[i] = data[j];
data[j] = temp;
i++;
j--;
}
if(left < j)
quicksort(left,j);
if(i < right)
quicksort(i,right);
}
和一个字母
template <typename T>
void Vector<T>::quicksort2(int left, int right)
{
int i = left;
int j = right;
String pivot = data[(left+right)/2];
if(i <= j)
{
while(data[i] < pivot)
i++;
while(pivot < data[j])
j--;
}
if(i <= j)
{
String temp = data[i];
data[i] = data[j];
data[j] = temp;
i++;
j--;
}
if(left < j)
quicksort2(left,j);
if(i < right)
quicksort2(i,right);
}
注意:这是通过我自己的自定义Vector和String类完成的,两个版本都运行得很好,所以我的主要问题是排序本身的逻辑 - 如何让它们一起运行。
此外,我只能使用iostream,fstream和cstring,以及我自己实现的任何其他内容。
提前致谢。
答案 0 :(得分:0)
我猜最终,你会希望它按一个单词的最小值排序。 一个简短的词比“长词”的“价值”更少,因为字母的重量小于单词,我会按每个单词的总ascii值对其进行排序。 在这种情况下,您不需要使用2种排序并合并,计算每个对象的ascii值并按其排序。
答案 1 :(得分:0)
如果您必须将两种算法链接在一起,对于学校作业或其他任何内容,您将需要实现稳定分区(或使用std :: stable_partition)。
编辑 - 在阅读“注意”之后,我应该提到另一种安抚教师的方法是实现第三版的快速排序,它使用谓词中的两个标准。请参阅下面的shorter_less
。更好的是,将谓词作为函数指针传递给单个统一的快速排序,std :: sort和std :: stable_sort就是这样做的。即...
以下是一次性完成所有操作的C ++方法......
#include <string>
#include <algorithm>
#include <vector>
using std::string;
static bool shorter_less( const string& L, const string &R) {
if (L.length() == R.length()) return L<R;
else return L.length() < R.length();
}
int main() {
using str_vec = std::vector<string>;
str_vec vec{ "xxzy" , "Alphonse", "Betty", "pea", "nuts", "z" };
std::sort(vec.begin(), vec.end(), shorter_less);
}
答案 2 :(得分:0)
只需使用std
从明智的实现中倒退,即可重新实现(缩减)您使用的事物的版本。
sort(vec.begin(), vec.end(), [](auto & lhs, auto & rhs){ return tie(lhs.size(), lhs) < tie(rhs.size(), rhs); });
然后,我们需要实现tuple
,sort
和tie
struct tuple
{
const int & first;
const String & second;
};
bool operator<(const tuple & lhs, const tuple & rhs)
{
if (lhs.first < rhs.first) return true;
if (rhs.first < lhs.first) return false;
return lhs.second < rhs.second;
}
tuple tie(const int & first, const String & second)
{
return { first, second };
}
然后我们可以调整您对Vector::quicksort
的实施方式
template <typename Iter, typename Comp>
void quicksort(Iter left, Iter right, Comp comp)
{
auto distance = (right - left) / 2
Iter l = left;
Iter pivot = left + distance;
Iter r = right;
if(l <= r)
{
for(;comp(*l, *pivot); ++l);
for(;comp(*pivot, *r); --j);
}
if(i <= j)
{
String temp = *i;
*i = *j;
*j = temp;
++i;
--j;
}
if(left < j)
quicksort(left, j, comp);
if(i < right)
quicksort(i, right, comp);
}
或者我们可以改为查看this Q&A,并实现partition
,find_if_not
等
template<class FwdIt, class Compare = std::less<>> void quick_sort(FwdIt first, FwdIt last, Compare cmp = Compare{}) { auto const N = distance(first, last); if (N <= 1) return; auto const pivot = *next(first, N / 2); auto const middle1 = partition(first, last, [=](auto const& elem){ return cmp(elem, pivot); }); auto const middle2 = partition(middle1, last, [=](auto const& elem){ return !cmp(pivot, elem); }); quick_sort(first, middle1, cmp); // assert(std::is_sorted(first, middle1, cmp)); quick_sort(middle2, last, cmp); // assert(std::is_sorted(middle2, last, cmp)); } template<class ForwardIt, class UnaryPredicate> ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p) { first = find_if_not(first, last, p); if (first == last) return first; for (ForwardIt i = next(first); i != last; ++i) { if (p(*i)) { iter_swap(i, first); ++first; } } return first; } template<class InputIt, class UnaryPredicate> constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) { for (; first != last; ++first) { if (!q(*first)) { return first; } } return last; } template<class InputIt> void iter_swap(InputIt a, InputIt b) { using value_type = typename InputIt::value_type; value_type temp = static_cast<value_type&&>(*a); // aka std::move *a = static_cast<value_type&&>(*b); *b = static_cast<value_type&&>(temp); } template<class T> void iter_swap<T*>(T * a, T * b) { T temp = static_cast<T&&>(*a); // aka std::move *a = static_cast<T&&>(*b); *b = static_cast<T&&>(temp); } template<class InputIt> InputIt next(InputIt it, int distance) { return it + distance; }