2011-04-01 36 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);