ग्राफ़ डेटा संरचना को लागू करने के लिए सबसे अधिक कुशल तरीका क्या है?


14

मैं आमतौर पर ग्राफ़ को दोगुनी लिंक वाली सूचियों के रूप में कार्यान्वित करता हूं, लेकिन यह मेरे अनुभव में काफी जगह अक्षम है क्योंकि मुझे कश्मीर के पड़ोसियों के लिए k पॉइंटर्स / संदर्भों की आवश्यकता है ताकि अप्रत्यक्ष ग्राफ़ के लिए मेरे गणित के सही होने पर सूचियों के भीतर ~ 2k पड़ोसी लिंक हों। क्या अंतरिक्ष को बचाने का एक बेहतर तरीका है? मुझे पता है कि यदि ग्राफ़ को निर्देशित किया गया है, तो कुछ लिंक को एकवचन बनाया जा सकता है, लेकिन क्या इससे बेहतर काम करने का कोई तरीका है?

जवाबों:


12

ठीक है, अगर अंतरिक्ष दक्षता आप सभी के बारे में परवाह है तो एक संकुचित डेटा संरचना सबसे अच्छा होगा - लेकिन निश्चित रूप से यह एक्सेस या अपडेट के लिए बहुत कुशल नहीं है ....।

यदि आपके ग्राफ़ में अपेक्षाकृत कम संख्या में नोड्स हैं और यह काफी सघन है (सभी संभावित कनेक्शनों के कम से कम 5% मौजूद होने की बात कहते हैं) तो आप पा सकते हैं कि एज लिस्ट्स का उपयोग करने के बजाय एक आसन्न मैट्रिक्स बनाने के लिए अधिक स्थान कुशल है । इसके लिए प्रति संभव केवल एक बिट (निर्देशित) कनेक्शन की आवश्यकता होती है, और n * n बिट्स कुल जहां आपके पास n नोड्स हैं।

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

कुछ तरकीबें हैं जिनसे आप इसके ऊपर प्रयास कर सकते हैं। उदाहरण के लिए, आप लिंक के सबसेट को साझा करने का प्रयास कर सकते हैं (यदि A और B प्रत्येक C, D, E को संदर्भित करते हैं, तो केवल लिंक C, D, E की सूची को एक बार स्टोर करें .....)। हालांकि यह बहुत जल्दी जटिल हो जाएगा और मुझे संदेह है कि यह ज्यादातर मामलों में प्रयास के लायक होगा।

एक अन्य चाल - मान लें कि आपके ग्राफ़ में नोड्स की एक उचित संख्या है, तो आप निश्चित रूप से अनुक्रमित करके स्थान बचाएंगे - जैसे कि पूर्ण सूचक / संदर्भ के बजाय 16-बिट नोड इंडेक्स नंबर का उपयोग करना।


यदि सभी लिंक एक-निर्देशित हैं, तो केवल आधे नोड से उच्च नोड तक की बचत करके, आधे स्थान को बचा सकता है।
डिडुप्लिकेटर

6

यह आपके डेटा की संरचना पर निर्भर करने वाला है।

अप्रत्यक्ष किनारों के साथ घने ग्राफ के लिए, आप वास्तव में त्रिकोणीय मैट्रिक्स का प्रतिनिधित्व करने वाले बिट सरणियों की सूची को हरा नहीं सकते हैं। एक List<BitArray>उदाहरण के लिए। तार्किक रूप से, यह इस तरह दिखेगा:

 0123
0
11
211
3001
41010

वहां से, आप रूट बिटअरे के सूचकांक को एक सूची में सूचीबद्ध करने के लिए उपयोग कर सकते हैं जो आपके नोड डेटा को संग्रहीत करता है।

उदाहरण के लिए, नोड के सभी पड़ोसियों को प्राप्त करना इस तरह होगा:

// C#
List<Node> Nodes = /* populated elsewhere */
List<BitArray> bits = /* populated elsewhere */
public static IEnumerable<Node> GetNeighbours(int x)    
{
    for (int i = 0; i < bits[idx].Count; i++)
    {
        if (this.bits[idx][i])
            yield return this.Nodes[i];
    }

    for (int i = 0; i < this.Nodes.Count; i++)
    {
        if (idx < this.bits[i].Count && this.bits[i][idx])
            yield return this.Nodes[i];
    }    
}

(ध्यान दें कि आप डेटा की मात्रा के आधार पर, अनुक्रमणिका प्रकार भी चुन सकते हैं, बाइट या ushort होने के लिए या उन रेखाओं के साथ कुछ ऐसा हो जो सभी अनुक्रमणिका सकारात्मक हो। मैं इसे सूक्ष्म-अनुकूलन नहीं मानता क्योंकि यह तुच्छ है)

एक निर्देशित ग्राफ के लिए, आप कनेक्टिविटी को संग्रहीत करने के लिए बिट्स के एक * n सरणी के मार्ग पर जाएंगे ... जब तक कि नोड्स की संख्या की तुलना में यह बहुत विरल न हो, जहां आप सूचकांकों की आसन्न सूची में जा सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.