संतुलित बाइनरी पेड़ आपकी समस्या का समाधान करने के लिए सबसे अच्छी डेटा संरचना है। O(log N)
निकालें आइटम में
आइटम
- जोड़े
O(log N)
में बनाम O(N)
या O(log N)
में अपने निकटतम: आप निम्न कार्रवाई डब्ल्यू/लघुगणक जटिलता करने के लिए कर सकेंगे
तत्व या के लिए खोज रहे अपने द्विआधारी पेड़ में निकटतम कम ही सीमित है सरल है:
- अपनी कुंजी खोजने के लिए रूट से बच्चे के पेड़ के माध्यम से लंबवत रूप से जाएं। यदि कुंजी < नोड है, तो बाएं बच्चे के पास जाएं, अन्यथा दाहिने ओर।
- आप कुंजी पाया, तो लौट
- तो कुंजी नहीं मिला, निकटतम बाईं माता पिता एक आप देख रहे हैं हो जाएगा (निकटतम कम ही सीमित है)
- यदि कोई बाईं माता-पिता, अभी पिछले दौरा ले नोड, यह पेड़ में न्यूनतम नोड है।
बाइनरी पेड़ को कार्यान्वित करने का वर्णन करने वाले कई लेख हैं। फिर भी मैं एक प्रकार का हैक का उपयोग कर .NET Framework संग्रह का पुन: उपयोग करने जा रहा हूं :)
अब, मैं आपको SortedSet<T>
पेश कर रहा हूं जो स्वयं ही लाल-काले पेड़ है। इसमें एक कमी है, इसमें निकटतम नोड्स को तुरंत खोजने की कोई क्षमता नहीं है। लेकिन हम पेड़ में खोज के एल्गोरिदम को जानते हैं (यह 1 में वर्णित है) और इसे SortedSet<T>.Contains
विधि (नीचे * पर संकुचित) में लागू किया गया है। अब हम रूट से सभी नोड्स को हमारे कस्टम तुलनाकर्ता का उपयोग करके ट्रैवर्सल के दौरान अंतिम बार देखे गए नोड पर कैप्चर कर सकते हैं। उसके बाद हम ऊपर कलन विधि का उपयोग निकटतम कम बाध्य नोड पा सकते हैं:
public class LowerBoundSortedSet<T> : SortedSet<T> {
private ComparerDecorator<T> _comparerDecorator;
private class ComparerDecorator<T> : IComparer<T> {
private IComparer<T> _comparer;
public T LowerBound { get; private set; }
private bool _reset = true;
public void Reset()
{
_reset = true;
}
public ComparerDecorator(IComparer<T> comparer)
{
_comparer = comparer;
}
public int Compare(T x, T y)
{
int num = _comparer.Compare(x, y);
if (_reset)
{
LowerBound = y;
}
if (num >= 0)
{
LowerBound = y;
_reset = false;
}
return num;
}
}
public LowerBoundSortedSet()
: this(Comparer<T>.Default) {}
public LowerBoundSortedSet(IComparer<T> comparer)
: base(new ComparerDecorator<T>(comparer)) {
_comparerDecorator = (ComparerDecorator<T>)this.Comparer;
}
public T FindLowerBound(T key)
{
_comparerDecorator.Reset();
this.Contains<T>(key);
return _comparerDecorator.LowerBound;
}
}
आप देखते हैं कि निकटतम नोड खोजने सामान्य खोज से अधिक नहीं लेता है, अर्थात O(log N)
। तो, यह आपकी समस्या का सबसे तेज़ समाधान है। यह संग्रह निकटतम खोजने में SortedList<K, V>
जितना तेज़ है और इसके अतिरिक्त SortedSet<T>
जितना तेज़ है।
SortedDictionary<K, V>
के बारे में क्या? यह लगभग एक ही चीज़ को छोड़कर SortedSet<T>
जैसा ही है: प्रत्येक कुंजी का मूल्य होता है। मुझे उम्मीद है कि आप SortedDictionary<K, V>
के साथ ऐसा करने में सक्षम होंगे।
* decompiled SortedSet<T>.Contains
विधि:
public virtual bool Contains(T item)
{
return this.FindNode(item) != null;
}
internal virtual SortedSet<T>.Node FindNode(T item)
{
for (SortedSet<T>.Node node = this.root; node != null; {
int num;
node = num < 0 ? node.Left : node.Right;
}
)
{
num = this.comparer.Compare(item, node.Item);
if (num == 0)
return node;
}
return (SortedSet<T>.Node) null;
}
यह आपकी मदद कर सकते हैं: http://stackoverflow.com/questions/1690929/what-net-dictionary-supports-a-find-nearest-key-operation –