按字母顺序对结构数组进行排序

4

我有一个结构数组(A[#]),名为Sheep(因为我的任务与羊的DNR有关)。在我完成任务后,我留下了这个结构体:

struct Sheep 
{
    string Vardas;
    char Fragmentas[CMax]; 
    int atitikme = 0; 
};

在我的 IT 中,数据是:

(string Vardas) | (char Fragmentas[CMax]) | (int atitikme)
Baltukas   TAGCTT 3
Bailioji   ATGCAA 3 
Smarkuolis AATGAA 1 

(char Fragmentas[CMax]不会使用,因此您不必查看它,我只是为了让它清晰明了而命名。)

所有这些数据都来自U2.txt文件,不能在代码中手动输入。

所有剩下的工作就是按照以下规则进行排序:

  1. 按'int atitikme'从大到小排序。
  2. 如果'int atitikme'相等,则必须按'a'字母序排列'A[#].Vardas'

为了按'int atitikme'排序,我创建了一个代码:

string q;
char w[20];
int e;
for (int o = 0; o < n-1; o++) 
{
    for (int p = o+1; p < n-1; p++) 
    {
        if (A[p].atitikme > A[o].atitikme) 
        {
            // - Vardo Keitimas
            q = A[o].Vardas;
            A[o].Vardas = A[p].Vardas;
            A[p].Vardas = q;
            // - A[#].atitikme keitimas
            e = A[o].atitikme;
            A[o].atitikme = A[p].atitikme;
            A[p].atitikme = e;
            // - DNR farkmentu keitimas
            for (int r = 0; r < m; r++) 
            {
                w[r] = A[o].Fragmentas[r];
                A[o].Fragmentas[r] = A[p].Fragmentas[r];
                A[p].Fragmentas[r] = w[r];
             }
        }
    }
}

n = 4 | m = 6

我需要添加什么来使这段代码运行:

else if (A[p].atitikme == A[o].atitikme) 
{
    <code>
}

如果“atitikme”等于另一个“atitikme”,那么A[p].Vardas和A[o].Vardas必须按字母顺序排序,但仅限于整个数组中的这两个元素。
或者,如果难以理解我的意思,是否可以在答案框中发布一段代码,在其中对2个字符串进行字母顺序排序?
注意:整行数据
(string Vardas) (char Fragmentas[CMax]) (int atitikme)
必须保持不变,只是该行中的位置必须不同,并按照我之前提到的规则进行排序。
输出应为:
Bailioji   3
Baltukas   3
Smarkuolis 1

编辑: 我的当前输出为:

Baltukas   3
Bailioji   3
Smarkuolis 1

P.s。该任务允许使用任何 C++ 相关的内容,无需创建或阅读任何其他文件。


2
为什么不使用std::vector和std::sort呢? - Tyker
你能使用std::sort吗?还是这是一些关于自己编写排序算法的C++练习? - PiotrNycz
5
我强烈建议你开始使用英文变量名,这样可以使沟通更容易。注释也是如此。另外,请使用描述性的变量名,而不是单个字母。如果你一年后再看你的代码,你可能完全不知道 o 或 p 是什么。 - Aziuth
3
@Lith,我不仅仅是在StackOverflow上这样认为。我是指一般情况下。无论你是哪个国家的人,你的代码应该始终使用英语编写。我自己也不是以英语为母语的人,但我也是这么做的。现在,也许你能够独自完成一个程序,但在未来,你可能会参与一个由多个国家参与的项目。那时,你会希望用英语编写成为你的日常习惯。 - Aziuth
@Aziuth,我没有想到那个。谢谢你。我会在我的其他自制项目或从互联网上找到的项目中使用你的建议,这些项目没有指定要使用哪种语言。 再次感谢你 :) - Lith
显示剩余3条评论
3个回答

5
我使用了std::vector<>而不是数组来存储羊。其次,使用std::sort()和一个lambda函数,您可以轻松地指定如何对std::vector<>/ Sheeps中的元素进行排序。这将是最简单的方法。
以下是现成代码,供查看:https://www.ideone.com/ay7TWU
#include <iostream>
#include <vector>
#include <algorithm>

struct Sheep
{
   std::string Vardas;
   std::vector<char> Fragmentas;
   int atitikme;
};

int main()
{
  std::vector<Sheep> vec =
   {
      {"Baltukas",  {'T','A','G','C','T','T'}, 3},
      {"Bailioji",  {'A','T','G','C','A','A'}, 3},
      {"Smarkuolis",{'A','A','T','G','A','A'}, 1},
      {"Hmarkuolis",{'A','A','T','G','A','A'}, 1},
      {"Kmarkuolis",{'A','A','T','G','A','A'}, 2}
   };

   std::sort(vec.begin(), vec.end(), [](const Sheep& lhs, const Sheep& rhs)
      {
         return (lhs.atitikme == rhs.atitikme) ? 
            lhs.Vardas < rhs.Vardas: // if atitikme's of sheeps are equal
            lhs.atitikme > rhs.atitikme; // if atitikme's of sheeps are not equal
      });

    for (const auto& it: vec)
        std::cout << it.Vardas << " " << it.atitikme << "\n";

    return 0;
}

输出结果:

Bailioji 3
Baltukas 3
Kmarkuolis 2
Hmarkuolis 1
Smarkuolis 1

2

最好逐个解决您的问题。

首先 - 定义排序顺序 - 参见文档 - 例如在std::less中。

因此,您需要定义排序顺序的函数对象类:

class SheepOrder
{
public:
    bool operator() ( const Sheep& left, const Sheep& right) const
    {
        // It goes from bigger to smaller by 'int atitikme'.
        if (left.atitikme > right.atitikme)
             return true;
        if (left.atitikme < right.atitikme)
             return false;

        //IF 'int atitikme' is equal then it will have to sort it in a in alphabetical order. 
        // I guess you meant Vardas
        return left.Vardas < right.Vardas;
    }
};

现在,已经定义了顺序 - 只需使用std::sort - 它可以与数组一起使用 - 没有问题:

Sheep sheeps[100];
// .. 
std::sort(std::begin(sheeps), std::end(sheeps), SheepOrder{});

或者:

void sortSheeps(Sheep* array, std::size_t numOFSheeps)
{
    std::sort(array, array + numOfSheeps, SheepOrder{});
}

您还可以使用std::tuple来更轻松地定义排序顺序(如果元素也具有此运算符,则元组默认具有运算符<):

class SheepOrder
{
public:
    bool operator() ( const Sheep& left, const Sheep& right) const
    {
        return tieMembersForSorting(left) < tieMembersForSorting(right);
    }
private:
    static auto tieMembersForSorting( const Sheep& object)
    {
        return std::make_tuple(-object.atitikme, // - to revert order
                               std::ref(object.Vardas)); // ref - to not make copy of string
    } 
};

如果将 tieMembersForSorting 定义为自由函数,也可以使用lambda表达式(因为它只有一行代码):

    inline auto tieMembersForSorting( const Sheep& object)
    {
        return std::make_tuple(-object.atitikme, // - to revert order
                               std::ref(object.Vardas)); // ref - to not make copy of string
    } 

    std::sort(begin(...), end(...), [](Sheep const& left, Sheep const& right)
              { return tieMembersForSorting(left) < tieMembersForSorting(right); });                    

2
使用 std::tie 要比使用 std::make_tuple 更简单,也不需要处理 std::ref - Slava
为什么不使用lambda而不是SheepOrder? - Tyker
可以的,只需在原地进行操作,不需要使用辅助函数并交换左右。 - Slava
1
你完全不需要使用 tieMembersForSorting - Slava
@Caleth - 对我来说DRY的意思是,当我需要更改某些内容时,我只需在一个地方进行更改。如果我需要将“atitikme,Vardas”的排序顺序更改为“Vardas,atitikme”- 那么我只需要一次更改就可以了,而不是两次... - PiotrNycz
显示剩余7条评论

1

https://en.cppreference.com/w/cpp/algorithm/sort展示了如何使用std::sort函数。

你需要编写一个函数bool less_than(const Sheep& a, const Sheep& b),该函数表示两只绵羊的顺序,然后简单地调用std::sort(container.begin(), container.end(), less_than);,其中container是类似于一组绵羊的向量。

编辑:函数如下:

bool less_than(const Sheep& a, const Sheep& b)
{
    if(a.atitikme != b.atitikme) return a.atitikme < b.atitikme;
    return a.Vardas < b.Vardas;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接