并行数组中的两组数据排序

时间:2011-04-01 06:31:35

标签: c++ sorting multidimensional-array

我目前正在尝试对阵列进行排序时遇到困难(我真的需要解决这个问题,我总是在排序数据时遇到问题)。

所以基本上我创建了一个包含“date”和“snowDepth”元素的C ++结构。我使用了bubblesort逻辑来对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 个答案:

答案 0 :(得分:2)

您可以为单个日期/ snowDepth对创建结构,并保留此类对的数组。之后可以在那里添加更多字段,并按您喜欢的方式排序。数据将始终保持一致。

顺便说一句:为什么泡泡排序? Quicksort要快得多。

答案 1 :(得分:1)

由于两个元素都在同一个结构中,因此这两个元素应该一起移动。你的数组应该是一个结构数组。你现在如何配置它?

答案 2 :(得分:1)

更新添加了一个基于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"));
}

我提到我有点懒吗?因此,使用流操作符显示项目的hack。 要使用自定义排序,请参阅here,例如

答案 3 :(得分:1)

因为你在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);

另请参阅this stackoverflow question

编辑: std :: pair.second不是函数。

答案 4 :(得分:1)

如果您的家庭作业专门用于学习编写排序算法,请替换此代码:

// 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);

P.S。您的数据类型Array名称不正确。它没有数组,只有一个观察点。

答案 5 :(得分:0)

你太近了!您比较数组元素的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值(因为它们是同一结构的成员)。

答案 6 :(得分:0)

您已经将数据存储在结构中,因此最简单的事情实际上就是定义运算符&lt;并换取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);