Сортировка двух наборов данных в параллельном массиве - PullRequest
3 голосов
/ 01 апреля 2011

В настоящее время мне очень трудно пытаться отсортировать массив (мне действительно нужно над этим работать, у меня всегда возникают проблемы при сортировке данных).

Итак, в основном я создал структуру C ++, которая содержит элементы date и snowDepth. Я использовал логику сортировки пузырьков для сортировки элемента snowDepth, который потрясающий и это именно то, что мне нужно. Однако, поскольку элементы являются отдельными, даты не меняются. Как я могу отсортировать параллельный массив ??

Данные должны выглядеть так:

  Snow Report  December 12 - 18
      Date            Base
       13             42.3
       12             42.5
       14             42.8
       15             43.1
       18             43.1
       16             43.4
       17             43.8

и мой выглядит так:

    SNOW REPORT    December 12 - 18
=======================================
       DATE             DEPTH
        12              42.3
        13              42.5
        14              42.8
        15              43.1
        16              43.1
        17              43.4
        18              43.8

Обратите внимание, что даты не сортируются вместе с элементом snowDepth. Как мне это сделать?

Хорошо, спасибо за все комментарии, ребята! Вот мой код:

// Structure
struct Array
{
    int date;
    double snowDepth;

    void SnowData(int d, double sD)
    {
        date = d;
        snowDepth = sD;
    }
};

// Main Function
int main()
{
    /* *--------------------*
       |      VARIABLES     |
       *--------------------* */

    // Constant Variables
    const int NUM_ELEMENTS = 7;
    const int NUM_MONTHS = 12;

    // String, Numerical, and Boolean Variables
    string month;
    int startDate;
    int endDate;
    int a;
    int b;
    int flag = 0;
    double result;
    bool monthMatch = false;

    // Array Variables
    Array snowData[NUM_ELEMENTS];
    string name[NUM_MONTHS] = {"January", "February", "March",
                               "April",   "May",      "June",
                               "July",    "August",   "September",
                               "October", "November", "December"  };


    /* *--------------------*
       | USER  INSTRUCTIONS |
       *--------------------* */    

    cout << endl;
    cout << "This program will keep track of the local snow conditions for 7 days." << endl;
    cout << "This program will ask the user for the month, date range (must be 7 days)," << endl;
    cout << "and the inches of snow reported on that date.  The program will then sort" << endl;
    cout << "the data from least amount of snow reported to the most." << endl;
    cout << endl;


    /* *--------------------*
       |     USER PROMPT    |
       *--------------------* */

    // Prompt the user for the month
    cout << "Enter the full name of the month: ";
    cin >> month;

    // Prompt the user for the starting date
    cout << "Enter the starting date of the 7-day period: ";
    cin >> startDate;
    snowData[0].date = startDate;

    // Once the user enters the start date, run a loop to initialize the rest of the dates in snowData array
    for (int x = 1; x < NUM_ELEMENTS; x++)
        snowData[x].date = ++startDate;

    // Prompt the user for the ending date
    cout << "Enter the ending date of the 7-day period: ";
    cin >> endDate;
    cout << endl;

    // If the user does not enter the correct ending date (which is 7 days from the start date), loop will prompt the user again
    if (endDate != snowData[NUM_ELEMENTS - 1].date)
    {
        do
        {
            cout << "The end date entered is not 7 days from the start date. Try again." << endl;
            cout << "Enter the ending date of the 7-day period: ";
            cin >> endDate;
            cout << endl;

        } while (endDate != snowData[NUM_ELEMENTS - 1].date);

        int x = 0;

        // Once the user enters the correct ending date, prompt the user for the snow depth numbers
        for (int y = 0; y < NUM_ELEMENTS; y++)
        {
            cout << "Enter the depth of snow measured on " << month << " " << snowData[x].date << ": ";
            cin >> snowData[y].snowDepth;
            x++;
        }
    }

    // Once the user enters the correct ending date, prompt the user for the snow depth numbers
    else
    {
        int x = 0;

        for (int y = 0; y < NUM_ELEMENTS; y++)
        {
            cout << "Enter the depth of snow measured on " << month << " " << snowData[x].date << ": ";
            cin >> snowData[y].snowDepth;
            x++;
        }
    }

    /* *--------------------*
       |  SORTING & FORMAT  |
       *--------------------* */

    // Sorting logic in ascending order
    for (a = 1; (a <= NUM_ELEMENTS) && flag; a++)
    {
        flag = 0;

        for (b = 0; b < (NUM_ELEMENTS - 1); b++)
        {
            if (snowData[b + 1].snowDepth < snowData[b].snowDepth)
            {
                result  = snowData[b].snowDepth;                
                snowData[b].snowDepth = snowData[b + 1].snowDepth;                
                snowData[b + 1].snowDepth = result;

                flag = 1;
            }
        }
    }

    // Formatted Output
    cout << endl;
    cout << "    SNOW REPORT    ";
    cout << month << " " << snowData[0].date << " - " << snowData[6].date << endl;
    cout << "=======================================" << endl;
    cout << setw(11) << "DATE" << setw(18) << "DEPTH" << endl;

    for (int x = 0; x < (NUM_ELEMENTS); x++)
        cout << setw(10) << snowData[x].date << setw(18) << snowData[x].snowDepth << endl;

    cout << endl;
}

Ответы [ 7 ]

2 голосов
/ 01 апреля 2011

Вы можете создать структуру для одной пары date / snowDepth и сохранить массив таких пар.После того, как вы можете добавить больше полей и сортировать по своему вкусу.Данные всегда будут согласованными.

Кстати: почему пузырьковая сортировка?Быстрая сортировка намного быстрее.

1 голос
/ 01 апреля 2011

Если ваше домашнее задание касается обучения написанию алгоритма сортировки, замените этот код:

// Sorting logic in ascending order
...
            result  = snowData[b].snowDepth;                
            snowData[b].snowDepth = snowData[b + 1].snowDepth;                
            snowData[b + 1].snowDepth = result;
...

следующим:

// Sorting logic in ascending order
...
            Array tmp  = snowData[b];                
            snowData[b] = snowData[b + 1];                
            snowData[b + 1] = tmp;
...

Если ваше задание не относится к обучениюнаписать сортировку, используйте std::sort:

bool Array::operator<(const Array& rhs) const { return this->snowDepth < rhs.snowDepth; }
...
// Sorting logic in ascending order
std::sort(snowData, snowData+NUM_ELEMENTS);

Ps Ваш тип данных Array назван неправильно.Он не содержит массив, он содержит одно наблюдение.

1 голос
/ 01 апреля 2011

Поскольку вы задали этот вопрос под тегом C ++, в C ++ есть один способ:

typedef std::pair<Date, double> SnowReportItem;
std::vector<SnowReportItem> SnowReport;
struct sort_criteria {
    bool operator()(const SnowReportItem &a, const SnowReportItem &b)
    { return a.second < b.second; }
};

SnowReport.push_back(make_pair(Date("12 Feb 2011"), 42.5));
// similar ones for the others ...

std::sort(SnowReport.begin(), SnowReport.end(), sort_criteria);

Кроме того, см. этот вопрос о стековом потоке .

РЕДАКТИРОВАТЬ: std :: pair.second не является функцией.

1 голос
/ 01 апреля 2011

Обновление Для хорошей меры добавлен пример на основе std :: map (см. Ниже)

Я бы не работал над сортировкой так же, как над структурами данных:)

Вот пример, который я написал, чтобы стереть пыль с моих навыков C ++ :) Извините, если я добавил больше, чем кухонная раковина.

Также обратите внимание, что для этого типа данных 'tivial' вы, вероятно, могли бы использовать std :: pair в качестве структуры 'Report' и std :: map в качестве типа контейнера, что требует значительно меньшего количества ручного кодирования, но я хотелпокажет вам, как все делается, если вы закодировали структуру вручную:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>

static struct Report 
{ 
    int date; 
    double base; 
    Report(int d, double b) : date(d), base(b) {} 

    bool operator<(const Report& rhs) const
    {
        return (date<rhs.date) || ((date==rhs.date) && (base<rhs.base));
    }

    friend std::ostream& operator<<(std::ostream& os, const Report& r)
    {
        os << "Report(" << r.date << ", " << r.base << ")";
    }
} theData[] = { 
       Report( 13, 42.3),
       Report( 12, 42.5),
       Report( 14, 42.8),
       Report( 15, 43.1),
       Report( 18, 43.1),
       Report( 16, 43.4),
       Report( 17, 43.8),
   };


int main(int argc, const char* args[])
{
    Report *const begin = theData;
    Report *const end   = theData+(sizeof(theData)/sizeof(*theData));

    // simpler container, take a copy for comparison
    std::vector<Report> simplerData(begin, end);

    // just sort it
    std::sort(begin, end);

    // VERIFY by printing to console
    std::cout << "Verify sorted array: " << std::endl;
    std::copy(begin, end, std::ostream_iterator<Report>(std::cout, "\n"));
    std::cout << "=====================" << std::endl;

    std::cout << "Verify unsorted copy:" << std::endl;
    std::copy(simplerData.begin(), simplerData.end(), std::ostream_iterator<Report>(std::cout, "\n"));
    std::cout << "=====================" << std::endl;

    // Sort that as well - for fun, reversed
    std::sort(simplerData.begin(), simplerData.end(), std::not2(std::less<Report>()));

    std::cout << "Verify reversed copy:" << std::endl;
    std::copy(simplerData.begin(), simplerData.end(), std::ostream_iterator<Report>(std::cout, "\n"));
    std::cout << "=====================" << std::endl;
}

Скомпилируйте и запустите, используя:

g++ -o test test.cpp
./test

Вывод:

Verify sorted array: 
Report(12, 42.5)
Report(13, 42.3)
Report(14, 42.8)
Report(15, 43.1)
Report(16, 43.4)
Report(17, 43.8)
Report(18, 43.1)
=====================
Verify unsorted copy:
Report(13, 42.3)
Report(12, 42.5)
Report(14, 42.8)
Report(15, 43.1)
Report(18, 43.1)
Report(16, 43.4)
Report(17, 43.8)
=====================
Verify reversed copy:
Report(18, 43.1)
Report(17, 43.8)
Report(16, 43.4)
Report(15, 43.1)
Report(14, 42.8)
Report(13, 42.3)
Report(12, 42.5)
=====================

Для полноты, вот как это будет выглядеть при использовании std :: map, как я предложил выше.Обратите внимание, что упорядочение по ключам неявно:

namespace std // hacky, google Koenig lookup...
{
    template <class K, class V> static std::ostream& operator<<(std::ostream& os, const std::pair<K, V> p)
        { os << "[" << p.first << ", " << p.second << "]"; }
}

void static UsingStdMap()
{
    typedef std::map<int, double> Reports;
    typedef Reports::value_type Report;

    static const Report initializer[] = {Report(13,42.3),Report(12,42.5),Report(14,42.8),Report(15,43.1),Report(18,43.1),Report(16,43.4),Report(17,43.8)};
    Reports theMap(initializer, initializer+sizeof(initializer)/sizeof(*initializer));

    std::copy(theMap.begin(), theMap.end(), std::ostream_iterator<Report>(std::cout, "\n"));
}

Я упоминал, что я немного ленив?Отсюда и взлом для отображения элементов с помощью оператора потока.Чтобы использовать заказ, см. здесь , например

1 голос
/ 01 апреля 2011

Поскольку оба элемента находятся в одной и той же структуре, эти два элемента должны двигаться вместе. Ваш массив должен быть массивом структур. Как у вас это настроено сейчас?

0 голосов
/ 02 марта 2016

Вы уже храните данные в структуре, поэтому на самом деле проще всего было бы просто определить operator <и поменять местами тип <code>Array.

struct Array
{
    int date;
    double snowDepth;

    void SnowData(int d, double sD)
    {
        date = d;
        snowDepth = sD;
    }

    friend bool operator<(const SnowData &a, const SnowData &b)
    {
        return a.date < b.date;
    }

    friend void swap(SnowData &a, SnowData &b)
    {
        using std::swap;
        swap(a.date, b.date);
        swap(a.snowDepth, b.snowDepth);
    }
};

// ...later... sort the array
std::sort(snowData, snowData + NUM_ELEMENTS);
0 голосов
/ 01 апреля 2011

Вы были так близко!Это правильно, что вы сравниваете snowDepth значения элементов массива, но вы не должны просто переупорядочивать эти значения.Вместо этого вы должны переупорядочить целое Array значение.

Вместо этого:

result  = snowData[b].snowDepth;
snowData[b].snowDepth = snowData[b + 1].snowDepth;
snowData[b + 1].snowDepth = result;

Сделайте это:

Array temp = snowData[b];
snowData[b] = snowData[b + 1];
snoData[b + 1] = temp;

Это переместит snowDepth значение и date значение (потому что они являются членами одной и той же структуры).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...