Search code examples
c++bubble-sortenumerated-types

Bubblesort Struct Array with Enumerated Direction/Type


I have a function sort, being passed an Array of structs.

Structs contain strings.

struct studentStruct {                                                                                                                      
  string firstName;
  string lastName;
  int grade;
  float GPA;
};

I'm passing this array of structs to a sorting function, as well as 2 enumerated types.

enum sortField {eFirstName, eLastName, eGrade, eGPA};                                                                                                   
enum sortDirection {eAscending, eDescending};

Now, I have to use Bubblesort and a compData function, so;

void sort( studentStruct s[], enum sortField field, int length, sortDirection d)
{
  for(int i = 0; i < length - 1; i++)
    {
      for(int j = 0; j < length - 1 - i; j++)
        {
          if(compData(s[j], s[j+1], field, d) == true)
            {
              swap(s[j], s[j+1]);
              cout << "SWAP" << endl;
            }
        }
    }
}
bool compData( studentStruct s1, studentStruct s2,  sortField field, sortDirection direction)
{
  switch(field)
    {
    case eFirstName:
      {
        string f1 = s1.firstName;
        string f2 = s2.firstName;
        switch(direction)
          {
          case eAscending:
            {
              if(f2 < f1)
                return true;
            }
          case eDescending:
            {
              if(f2 > f1)
                return true;
            }
          }
      }
    }
}

So; I pass sort my Array of Structs s[], it calls compData to decide whether or not to switch s[j] and s[j+1]. compData looks at the enumerated values to decide how we are comparing s[j] and s[j+1], selects to sort on eFirstName, eAscending, and sort accordingly.

But in actuality, I pass sort(s[], eFirstName, 10, eAscending) and I'm getting an improperly sorted mess. For 5 inputs of M, I, K, O, N, I'm getting out N, O, K, I, M; its just flipping the array.


Solution

  • Your comparison function is mostly missing, but the parts that are there suggest you have no path to ever return a definitive false, which is mandatory for a proper comparator.

    Second, you call order of arguments is wrong. The "right" side argument should be first, the "left" side second. if the comparator answers true, they're in the wrong order and should be swapped.

    Addressing both of those (and granting you an improved bubblesort with early exit detection on already-sorted sequences), the result functions as intended:

    #include <iostream>
    #include <algorithm>
    
    enum sortField {eFirstName, eLastName, eGrade, eGPA};
    enum sortDirection {eAscending, eDescending};
    
    struct studentStruct {
        std::string firstName;
        std::string lastName;
        int grade;
        float GPA;
    };
    
    bool compData( studentStruct s1, studentStruct s2, sortField field, sortDirection direction)
    {
        bool result = false;
    
        switch(field)
        {
            case eFirstName:
                switch(direction)
                {
                    case eAscending:
                        result = s1.firstName < s2.firstName;
                        break;
    
                    case eDescending:
                        result = s2.firstName < s1.firstName;
                        break;
                }
                break;
    
            case eLastName:
                switch(direction)
                {
                    case eAscending:
                        result = s1.lastName < s2.lastName;
                        break;
    
                    case eDescending:
                        result = s2.lastName < s1.lastName;
                        break;
                }
                break;
    
            case eGrade:
                switch(direction)
                {
                    case eAscending:
                        result = s1.grade < s2.grade;
                        break;
    
                    case eDescending:
                        result = s2.grade < s1.grade;
                        break;
                }
                break;
    
            case eGPA:
                switch(direction)
                {
                    case eAscending:
                        result = s1.GPA < s2.GPA;
                        break;
    
                    case eDescending:
                        result = s2.GPA < s1.GPA;
                        break;
                }
                break;
        }
    
        return result;
    
    }
    
    void sort( studentStruct s[], enum sortField field, int length, sortDirection d)
    {
        bool swapped = true;
        while (swapped && length-- > 0)
        {
            swapped = false;
            for (int i=0; i<length; ++i)
            {
                if (compData(s[i+1], s[i], field, d))
                {
                    std::cout << "SWAP" << '\n';
                    std::swap(s[i+1], s[i]);
                    swapped = true;
                }
            }
        }
    }
    
    int main()
    {
        studentStruct students[] = { {"M"}, {"I"}, {"K"}, {"O"}, {"N"} };
        sort(students, eFirstName, 5, eAscending);
    
        for (auto const& s : students)
            std::cout << s.firstName << '\n';
    }
    

    Output

    SWAP
    SWAP
    SWAP
    I
    K
    M
    N
    O