2010-07-21 13 views
5

मैं एक क्वाड्री-जैसी डेटा संरचना लिख ​​रहा हूं जिसमें जेनेरिक ऑब्जेक्ट्स T के मैट्रिक्स शामिल हैं। यदि चार सबनोड्स में T के परिभाषित मैट्रिक्स होते हैं, तो मैं उन्हें एक एकल, बड़े मैट्रिक्स में एकत्र करने जा रहा हूं, फिर सबनोड हटाएं। क्या हर संदर्भ के माध्यम से लूपिंग और इसे कॉपी करने से ऐसा करने का एक और अधिक प्रभावी तरीका है? क्या मैं इसके बजाय स्मृति के टुकड़ों की प्रतिलिपि बना सकता हूं?ऑब्जेक्ट्स के मैट्रिक्स को ऑब्जेक्ट्स के बड़े मैट्रिक्स में कुशलतापूर्वक कॉपी करना


उदाहरण:

T[,] _leaf1 = new T[64,64]; 
T[,] _leaf2 = new T[64,64]; 
T[,] _leaf3 = new T[64,64]; 
T[,] _leaf4 = new T[64,64]; 

// Populate leafs 

T[,] _root = new T[128,128]; 

CopyInto(ref _root, ref _leaf1, 64, 64); 
CopyInto(ref _root, ref _leaf2, 0, 64); 
CopyInto(ref _root, ref _leaf3, 0, 0); 
CopyInto(ref _root, ref _leaf4, 64, 0); 
+0

कैसे आप मैट्रिक्स बिल्कुल reprent करते हैं? कुल कैसे? यदि आइटम संदर्भ प्रकार हैं, तो आप केवल एक पॉइंटर (4/8 बाइट्स) की प्रतिलिपि बना रहे हैं, जो कि बहुत तेज है। वहाँ केवल 4 (सूचियों) आइटम हैं, है ना? –

+0

मैंने एक उदाहरण जोड़ा। मेरी संरचना में, '_leafX' एक बच्चे नोड में होगा, 'शून्य कॉपीइंटो (रेफरी टी [,], प्वाइंट पी)' – dlras2

+0

के साथ तो दूसरे शब्दों में: आप किसी अन्य मैट्रिक्स में मैट्रिक्स के तत्वों की प्रतिलिपि बना रहे हैं? आप 'Array.CopyTo' या 'Buffer.BlockCopy' का उपयोग कर सकते हैं (प्रतिलिपि केवल कई μs ले जाएगा)। साथ ही, यदि आप अपने डिज़ाइन को संशोधित करते हैं तो यह 'सरणी [64] 'नहीं है, लेकिन' सरणी [64 * 64]' है और पंक्तियों की जांच के लिए मॉड्यूलो ('%') का उपयोग करें, यह और भी तेज़ होगा। सुनिश्चित नहीं है कि आपकी प्रदर्शन बाधा कहां है। यह निर्भर करता है कि आप कितनी बार मैट्रिक्स बनाम तत्वों तक पहुंचते हैं। आप कितनी बार प्रतिलिपि बनाते हैं। –

उत्तर

1

यदि आप संरचना को अपरिवर्तनीय बना सकते हैं, तो आप शायद खुद को बहुत सारी प्रतियां बनाने से बचा सकते हैं। एरिक लिपर्ट में कुछ great posts about immutable structures है।

संपादित करें: फिर से, मैं अगर यह आपके मामले में प्रदर्शन में सुधार होगा पता नहीं है, लेकिन यहाँ अपरिवर्तनीय वस्तुओं के साथ एक संभव डिजाइन का एक उदाहरण है:

abstract class QuadTree<T> 
{ 
    public QuadTree(int width, int height) 
    { 
     this.Width = width; 
     this.Heigth = heigth; 
    } 

    public int Width { get; private set; } 
    public int Height { get; private set; } 

    public abstract T Get(int x, int y); 
} 

class MatrixQuadTree<T> : QuadTree<T> 
{ 
    private readonly T[,] matrix; 

    public QuadTree(T[,] matrix, int width, int heigth) 
     : base(width, heigth) 
    { 
     this.matrix = matrix; 
    } 

    public override T Get(int x, int y) 
    { 
     return this.matrix[x, y]; 
    } 
} 

class CompositeQuadTree<T> : QuadTree<T> 
{ 
    private readonly QuadTree<T> topLeft; 
    private readonly QuadTree<T> topRight; 
    private readonly QuadTree<T> bottomLeft; 
    private readonly QuadTree<T> bottomRight; 

    public CompositeQuadTree(QuadTree<T> topLeft, 
     QuadTree<T> topRight, QuadTree<T> bottomLeft, 
     QuadTree<T> bottomRight) 
     : base(topLeft.Width + topRight.Width, 
      topLeft.Height + bottomLeft.Heigth) 
    { 
     // TODO: Do proper checks. 
     if (this.Width != topLeft.Width + bottomRight.Width) 
      throw Exception(); 

     this.topLeft = topLeft; 
     this.topRight = topRight; 
     this.bottomLeft = bottomLeft; 
     this.bottomRight = bottomRight; 
    } 

    public override T Get(int x, int y) 
    { 
     if (x <= this.topLeft.Width) 
     { 
      if (y <= this.topLeft.Width) 
      { 
       return this.topLeft.Get(x, y); 
      } 
      else 
      { 
       return this.topLeft.Get(x, y + this.topLeft.Heigth); 
      } 
     } 
     else 
     { 
      if (y <= this.topLeft.Width) 
      { 
       return this.topRight.Get(x + this.topLeft.Width, y); 
      } 
      else 
      { 
       return this.topRight.Get(x + this.topLeft.Width, 
        y + this.topLeft.Heigth); 
      } 
     } 
    } 
} 

अब आप का उपयोग करने में सक्षम होगा यह इस प्रकार है:

T[,] _leaf1 = new T[64,64]; 
T[,] _leaf2 = new T[64,64]; 
T[,] _leaf3 = new T[64,64]; 
T[,] _leaf4 = new T[64,64]; 

// Populate leafs 

QuadTree<T> l1 = new MatrixQuadTree<T>(_leaf1,64,64); 
QuadTree<T> l2 = new MatrixQuadTree<T>(_leaf2,64,64); 
QuadTree<T> l3 = new MatrixQuadTree<T>(_leaf3,64,64); 
QuadTree<T> l4 = new MatrixQuadTree<T>(_leaf4,64,64); 

// Instead of copying, you can no do this: 
QuadTree<T> c = CompositeQuadTree<T>(l1,l2,l3,l4); 

// And you can even make composites, of other composites: 
QuadTree<T> c2 = CompositeQuadTree<T>(c,c,c,c); 

// And you can read a value as follows: 
T value = c2[30, 50]; 

फिर, अगर यह अपनी स्थिति में उचित है या क्या यह एक प्रदर्शन में सुधार देता है, क्योंकि आप अविवेक का एक स्तर है जब मूल्य मिल रहा है मैं नहीं जानता। हालांकि, इसे सुधारने के कई तरीके हैं, लेकिन यह इस बात पर निर्भर करता है कि आपको वास्तव में क्या करना है।

शुभकामनाएं।

+0

आप कैसे सुझाव देंगे कि मैं ऐसा करता हूं? मुझे यकीन नहीं है कि हम एक-दूसरे को समझते हैं .. – dlras2

+0

उत्तर अपडेट किया गया। – Steven

+0

यदि मैं ओपी के सही ढंग से समझता हूं, रूट मैट्रिक्स में पहले से ही कुछ डेटा हो सकता है, तो आप उन्हें आसानी से ओवरराइट करेंगे। लेकिन हो सकता है कि वह वह समाधान है जिसे वह ढूंढ रहा है - यह उसकी जरूरतों पर निर्भर करता है। वह वास्तव में एक 'क्वाडट्री' का उपयोग नहीं कर रहा है, बस एक साधारण मैट्रिक्स। –

0

हो सकता है कि मैं यहाँ जिस तरह से बंद आधार हूँ, लेकिन अगर आप T विवश एक संदर्भ प्रकार तो आप संदर्भ से ज्यादा कुछ नहीं है और डेटा की प्रतिलिपि की जाएगी होना करने के लिए अपने आप। तो नए मैट्रिक्स में T ऑब्जेक्ट्स के लिए केवल नए संदर्भ बनाएं और उन्हें पुराने मैट्रिक्स से हटा दें। यहां बताया गया है कि आप T को कैसे रोक सकते हैं। where और class कीवर्ड के उपयोग पर ध्यान दें।

public class Foo<T> where T: class 
{ 
} 
+0

एक बहुत अच्छा मुद्दा है, और यदि आवश्यकता हो तो मैं जेनेरिक वस्तुओं को प्रतिबंधित कर सकता हूं, लेकिन इसके लिए अभी भी प्रतिलिपि बनाने के लिए प्रत्येक पॉइंटर के माध्यम से लूपिंग की आवश्यकता है। – dlras2

+0

* @ ब्रायन * बिंदु एक समाधान ढूंढना है जिसके लिए लूपिंग की आवश्यकता नहीं है। मैं दूर हूं कि कक्षाओं के लिए, मैं पूरे ऑब्जेक्ट के डेटा की प्रतिलिपि नहीं बना रहा हूं। – dlras2

0

System.Buffer.BlockCopy शायद? वह स्मृति के टुकड़ों की प्रतिलिपि बनायेगा।

+0

मैं मैट्रिक्स पर ब्लॉककॉपी का उपयोग कैसे कर सकता हूं? यह केवल सरणी लेता है, और 'मैट्रिक्स [सी]' त्रुटियां। – dlras2

+0

जारोस्लाव ने मेरे सुझाव के आस-पास कुछ नमूना कोड बनाया, मैं बस उनके जवाब पर टिप्पणियों का पालन करने जा रहा हूं। –

+0

@ बेन: वास्तव में मैंने ओपी के उत्तर में मेरी टिप्पणियों में 'ब्लॉककॉपी' का सुझाव दिया है, इसलिए मैंने इसे उन टिप्पणियों के आसपास सटीक बनाने के लिए बनाया है। –

0

यदि आप असुरक्षित कोड का उपयोग करने से डरते नहीं हैं और आप संदर्भों का उपयोग कर सकते हैं, तो आप पुरानी स्टाइल पॉइंटर्स का उपयोग कर सकते हैं। आपको पहले अपने सरणी में fixed कीवर्ड का उपयोग करना होगा। बहुआयामी सरणी एक दूसरे के बाद प्रत्येक आयाम को संरेखित करती है।

0

मेरी टिप्पणी को उत्तर के रूप में रखने का फैसला किया।

तो दूसरे शब्दों में: आप किसी अन्य मैट्रिक्स में मैट्रिक्स के तत्वों की प्रतिलिपि बना रहे हैं? आप Array.CopyTo या Buffer.BlockCopy (प्रतिलिपि केवल कई μs ले सकते हैं) का उपयोग कर सकते हैं।

इसके अलावा, अगर आप अपने डिजाइन को संशोधित तो यह array[64] नहीं है, लेकिन array[64*64] और सापेक्ष (%) का उपयोग/गुणा (*)/सेट तत्वों प्राप्त करने के लिए, यह भी तेजी से किया जाएगा। सुनिश्चित नहीं है कि आपकी प्रदर्शन बाधा कहां है। यह निर्भर करता है कि आप कितनी बार मैट्रिक्स बनाम तत्वों तक पहुंचते हैं। आप कितनी बार प्रतिलिपि बनाते हैं।

public class Matrix<T> 
{ 
    private int size; 
    private T[] elements; 

    public Matrix(int size) 
    { 
     this.size = size; 
     this.elements = new T[size]; 
    } 

    T this[int x, int y] 
    { 
     get 
     { 
      return elements[x + (y*size)]; 
     } 
     set 
     { 
      elements[x + (y*size)] = value; 
     } 
    } 

    public void CopyTo(Matrix<T> destination, int x, int y) 
    { 
     int offset = x + (y*size); 
     T[] destinationArray = (T[])destination; 
     Buffer.BlockCopy(this.elements, 0, destinationArray, offset, this.elements.Length); 
    } 

    public static explicit operator T[] (Matrix<T> matrix) 
    { 
     return matrix.elements; 
    } 
} 

और कोड में:

Matrix<int> leaf = new Matrix<int>(64); 
Matrix<int> root = new Matrix<int>(128); 
leaf.CopyTo(root, 0, 0); 
+0

मुझे यकीन नहीं है कि यह वास्तव में काम करेगा ... एक 2x2 मैट्रिक्स '[[1,2] [3,4]]' पर विचार करें, एक सरणी के रूप में संग्रहीत '(1,2,3,4)'। इसे 4x4 मैट्रिक्स में सीधे कॉपी करने का कोई तरीका नहीं होगा, क्योंकि '[1,2]' और '[3,4] 'को विभाजित करने की आवश्यकता होगी। यह मुझे लगता है जैसे आपकी विधि बड़े मैट्रिक्स की पहली पंक्ति '[1,2,3,4] ' – dlras2

+0

हां, आपको पंक्ति से पंक्ति की प्रतिलिपि बनाना होगा, लेकिन आप कम से कम एक पूरी पंक्ति कॉपी कर सकते हैं व्यक्तिगत तत्वों की प्रतिलिपि बनाने के बजाय एक बार में। –

+0

@ Daniel: यह होगा, लेकिन आप matrices अन्य matrices के composites होने और सूचकांक बदलने के लिए सेट कर सकते हैं। 2x2 'तत्व [1,2,3,4]' और 4x4 'तत्वों [1,2,3,4, ए, बी, सी, डी, ई, एफ, जी, एच, ...] की तरह दिखेगा] । इसलिए ऑफसेट 0 से 3 पहले सबमिट्रिक्स का प्रतिनिधित्व करता है। आदि।या पंक्ति से पंक्ति की प्रतिलिपि बनाएँ :) –

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