2011-03-29 25 views
10

यह मूल रूप से इस प्रश्न का पुन: विश्राम है: Java: Multi-dimensional array vs. One-dimensional लेकिन सी # के लिए।बहु-आयामी सरणी बनाम एक आयामी

मेरे पास एक निश्चित मात्रा में तत्व हैं जो ग्रिड के रूप में स्टोर करने के लिए समझ में आता है। क्या मुझे सरणी [x * y] या सरणी [x] [y] का उपयोग करना चाहिए?

संपादित करें: ओह, तो एक आयामी सरणी [x * y], बहुआयामी सरणी [x, y] और jagged array [x] [y] हैं, और शायद मैं जंजीर चाहता हूं?

+1

मैं 'के बजाय' सरणी [x] [y] ' – Snowbear

उत्तर

10

jagged arrays (array[][]) का उपयोग करने के लिए सी # में कई फायदे हैं। वे वास्तव में बहुआयामी सरणी से अधिक प्रदर्शन करेंगे।

कहा जा रहा है कि, मैं व्यक्तिगत रूप से एकल आयामी सरणी के बजाय एक बहुआयामी या जंजीर सरणी का उपयोग करता हूं, क्योंकि इससे समस्या स्थान अधिक निकटता से मेल खाता है। एक आयामी सरणी का उपयोग करना आपके कार्यान्वयन में जटिलता जोड़ रहा है जो वास्तविक लाभ प्रदान नहीं करता है, खासकर जब 2 डी सरणी की तुलना में आंतरिक रूप से, यह अभी भी स्मृति का एक ब्लॉक है। array[x,y] की

+3

क्षमा' सरणी के रूप में 'multidimensional' सरणी [एक्स, वाई] को चिह्नित करना होगा लेकिन मुझे लगता है कि शब्द" दांतेदार सरणी "से नफरत है। .NET प्रलेखन वहां इतनी शब्दावली फेंकता है कि कोई सोचता है कि एक जंजीर सरणी एक नया डेटाटाइप था। यह सिर्फ सरणी की एक सरणी लटका है! – JonH

+3

@ जोनएच: हाँ, लेकिन इसके लिए यह आधिकारिक शब्द है, और सीएलआर में उनके साथ काम करने के लिए विशिष्ट अनुकूलन हैं। –

9

सकारात्मक:
- रनटाइम आप के लिए और अधिक जांच निष्पादित करेगा। प्रत्येक इंडेक्स एक्सेस की अनुमति सीमा के भीतर की जाएगी। एक और दृष्टिकोण के साथ आप a[y*numOfColumns + x] जैसे आसानी से smth कर सकते हैं जहां एक्स "कॉलम की संख्या" से अधिक हो सकता है और यह कोड अपवाद फेंकने के बिना कुछ गलत मूल्य निकाल देगा।
- अधिक स्पष्ट सूचकांक पहुंच। पूरे सरणी से अधिक आसान यात्रा -
: a[x,y]array[x*y] के क्लीनर की तुलना में a[y*numOfColumns + x]

पेशेवरों है। आपको दो की बजाय केवल एक लूप की आवश्यकता है।

और विजेता है ...array[x,y]

11

मैं अनुचित रूप से बड़ी सरणियों पर एक परीक्षण भाग गया और देखने के लिए कि दांतेदार सरणियों ([y] [x]) से अधिक तेजी से प्रतीत होते हैं हैरान था मैं पसंद करेंगे मैनुअल गुणा [y * ySize + x] के साथ एकल आयाम सरणी। और बहु ​​आयामी सरणी [,] धीमी हैं लेकिन इतनी ज्यादा नहीं।

बेशक आपको अपने विशेष सरणी पर परीक्षण करना होगा, लेकिन ऐसा लगता है कि अलग-अलग ऐसा नहीं लगता है, इसलिए आपको जो कुछ भी करना चाहिए, उसका उपयोग करना चाहिए जो आप सबसे अच्छा कर रहे हैं।

0.280 (100.0% | 0.0%) 'Jagged array 5,059x5,059 - 25,593,481' 
|  0.006 (2.1% | 2.1%) 'Allocate' 
|  0.274 (97.9% | 97.9%) 'Access' 


0.336 (100.0% | 0.0%) 'TwoDim array 5,059x5,059 - 25,593,481' 
|  0.000 (0.0% | 0.0%) 'Allocate' 
|  0.336 (99.9% | 99.9%) 'Access' 


0.286 (100.0% | 0.0%) 'SingleDim array 5,059x5,059 - 25,593,481' 
|  0.000 (0.1% | 0.1%) 'Allocate' 
|  0.286 (99.9% | 99.9%) 'Access' 



0.552 (100.0% | 0.0%) 'Jagged array 7,155x7,155 - 51,194,025' 
|  0.009 (1.6% | 1.6%) 'Allocate' 
|  0.543 (98.4% | 98.4%) 'Access' 


0.676 (100.0% | 0.0%) 'TwoDim array 7,155x7,155 - 51,194,025' 
|  0.000 (0.0% | 0.0%) 'Allocate' 
|  0.676 (100.0% | 100.0%) 'Access' 


0.571 (100.0% | 0.0%) 'SingleDim array 7,155x7,155 - 51,194,025' 
|  0.000 (0.1% | 0.1%) 'Allocate' 
|  0.571 (99.9% | 99.9%) 'Access' 



for (int i = 6400000; i < 100000000; i *= 2) 
{ 
    int size = (int)Math.Sqrt(i); 
    int totalSize = size * size; 

    GC.Collect(); 

    ProfileTimer.Push(string.Format("Jagged array {0:N0}x{0:N0} - {1:N0}", size, totalSize)); 

    ProfileTimer.Push("Allocate"); 

    double[][] Jagged = new double[size][]; 
    for (int x = 0; x < size; x++) 
    { 
     Jagged[x] = new double[size]; 
    } 

    ProfileTimer.PopPush("Allocate", "Access"); 

    double total = 0; 
    for (int trials = 0; trials < 10; trials++) 
    { 
     for (int y = 0; y < size; y++) 
     { 
      for (int x = 0; x < size; x++) 
      { 
       total += Jagged[y][x]; 
      } 
     } 
    } 

    ProfileTimer.Pop("Access"); 
    ProfileTimer.Pop("Jagged array"); 


    GC.Collect(); 

    ProfileTimer.Push(string.Format("TwoDim array {0:N0}x{0:N0} - {1:N0}", size, totalSize)); 

    ProfileTimer.Push("Allocate"); 

    double[,] TwoDim = new double[size,size]; 

    ProfileTimer.PopPush("Allocate", "Access"); 

    total = 0; 
    for (int trials = 0; trials < 10; trials++) 
    { 
     for (int y = 0; y < size; y++) 
     { 
      for (int x = 0; x < size; x++) 
      { 
       total += TwoDim[y, x]; 
      } 
     } 
    } 

    ProfileTimer.Pop("Access"); 
    ProfileTimer.Pop("TwoDim array"); 


    GC.Collect(); 

    ProfileTimer.Push(string.Format("SingleDim array {0:N0}x{0:N0} - {1:N0}", size, totalSize)); 

    ProfileTimer.Push("Allocate"); 

    double[] Single = new double[size * size]; 

    ProfileTimer.PopPush("Allocate", "Access"); 

    total = 0; 
    for (int trials = 0; trials < 10; trials++) 
    { 
     for (int y = 0; y < size; y++) 
     { 
      int yOffset = y * size; 
      for (int x = 0; x < size; x++) 
      { 
       total += Single[yOffset + x]; 
      } 
     } 
    } 

    ProfileTimer.Pop("Access"); 
    ProfileTimer.Pop("SingleDim array"); 
} 
+0

बहुत ही रोचक पोस्ट। मुझे code.google.com पर ProfileTimer मिला। पहले मैं आपके परिणामों को पुन: पेश नहीं कर सका। जालीदार सरणी के लिए स्मृति आवंटन बहुत धीमा था और 2-मंद पहुंच बहुत धीमी थी। फिर मैंने बिल्ड विकल्पों में "32-बिट पसंद करें" अनचेक किया और सबकुछ आपके परिणामों से बहुत निकटता से मेल खाता है। – dcaswell

संबंधित मुद्दे