C ++快速排序,有2个要求

时间:2018-03-03 22:36:45

标签: c++

我的目标是根据两个标准对单词列表进行排序:

  • 主要标准是增加字长,
  • 次要标准是按字母顺序

例如:

{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,以及我自己实现的任何其他内容。

提前致谢。

3 个答案:

答案 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); });

然后,我们需要实现tuplesorttie

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,并实现partitionfind_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;
}