2011-04-01 37 views
3

我目前正在尝试对数组进行排序(我确实需要处理这个问题,我总是在排序数据时遇到问题)。排序并行数组中的两组数据

所以基本上我创建了一个包含“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; 
} 
+1

如果你发布结构的代码和你的排序,那么它会更容易找出什么是错的。 – ChrisWue 2011-04-01 06:38:34

+0

同意。即使只是其中的一小部分。 – jonsca 2011-04-01 06:43:34

+0

也许你对这个项目的一些混淆来自于你有*并行数组*。你没有。你只有一个数组。这是一个结构数组,因此数组中的每个* single *元素都有*多个值*。但仍然只有一个阵列。如果您认为*有平行数组,那么您将需要完全丢弃“数组”数据类型。我建议你拿这段代码给你的老师,以确认你正朝着正确的方向前进,而不是浪费太多时间。 – 2011-04-02 18:40:18

回答

1

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

2

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

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

+0

这听起来像OP *是*在一个结构中持有。这让我非常困惑......我可能不得不弄清楚这一点。 ;) – jonsca 2011-04-01 06:39:29

+3

不错的建议,但不要用完并使用quicksort,请使用std :: sort。它保证在n个记录时间内运行,作为一个STL用户,你不应该在乎它是作为一个混合形式的quicksort还是魔法精灵来实现。它可以在不重新发明轮子的情况下完成工作。 – jeffythedragonslayer 2011-04-01 07:13:54

+0

同意da code monkey。 – weekens 2011-04-01 07:15:17

1

更新添加一个std ::根据图示例,好措施(见下文)

我不会排序,也取决于数据结构:)

在这里工作是一个示例,我写为了刷掉我的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")); 
} 

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

+0

恐怕,你的<运营商并不严格。如果我们有(20,43.1)和(19,44.2)呢?第一个<第二个?为什么?我们是按日期还是按基地排序? – weekens 2011-04-01 07:21:03

+0

@weekens:oops固定(主要由基地,看问题) – sehe 2011-04-01 08:21:50

+0

添加基于std :: map的示例后,我注意到[FrankH's answer](http://stackoverflow.com/questions/5509904/sorting-two-sets -of-data-in-parallel-array/5510822#5510822)它的快捷方式较少,而且非常简洁 – sehe 2011-04-01 09:30:09

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不是函数。

+0

这应该读取'struct sort_criteria_t {...} sort_criteria;'否则一个“不会引用一个值”编译器错误发布。 – Jason 2015-02-04 21:05:32

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值(因为它们是相同的结构成员)。

+0

-1用于暗示/不鼓励自己写排序算法。很明显,这个问题对于提问者来说太高级了,当stl定义nth_element,stable_partition,partial_sort等等等等时,不应该需要实现自定义排序算法......甚至inplace_merge !!!为了优化fests,你可以使用make_heap和family。 (_当这个规则应该有一个例外时,这个人真的会知道_) – sehe 2011-04-01 09:32:15

+0

@sehe OP看起来是在入门级的。我从过去的经验中得出的假设是,教授们不希望学生在理解如何为自己做好之前使用图书馆的功能。 – jonsca 2011-04-01 11:07:38

+0

@jonsca:那么在这里问这种冲突,那么,是不是 – sehe 2011-04-01 11:09:02

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

Ps您的数据类型Array被误称。它不包含数组,它拥有一个观察值。

0

您已经将数据存储在一个结构中,所以最简单的事情实际上就是为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);