いてどのようにお考えですか。純辞書に対応を検索する"最寄の鍵"に働きかけているのか?
-
18-09-2019 - |
質問
私変換するもC++のコードC#でstd::地図::lower_bound(k)の探エントリのmapがキーと同等以上。しかし、私は思われないという同じことです。ネSortedDictionary.思いが実施する回避策をSortedListが、残念ながらSortedListするのが遅すぎる(O(n)の挿入-削除するキー.どのようなことができますか?
注意:この回避策を用いることを活かし私の特定のシナリオ...具体的には、私のキーを緻密な人口の整数からわずか0で使ってリスト<TValue> 私の辞書のリストの指標としての検索キー値kができず、ループ回.でもね、その答えいたします。
解決 4
作成した三つのデータ構造に関連するアクセスにはログインが木に提供する機能を任意のデータタイプ: BList<T>
, BDictionary<K,V>
や BMultiMap<K,V>
.それぞれのデータ構造を提供 FindLowerBound()
や FindUpperBound()
法るようC++'s lower_bound
や upper_bound
.
他のヒント
これは、仕事の数ヶ月を要したが、最後に、私はこの問題に対する少なくとも部分的なソリューションを提供することができます...私は、コンパクトパトリシアトライ、「次の大きな鍵を見つける」操作を提供していますソートされた辞書を呼び出します。
http://www.codeproject.com/KB/recipes/cptrie.aspx の
これは、キーの唯一の特定の種類、すなわちbyte[]
、string
、およびすべてのプリミティブ整数型(Int8..UInt64)に支持されているので、部分的にしか解決策です。また、文字列のソートは大文字と小文字が区別されます。
の問題は、辞書/ハッシュテーブルはあなたが格納各値に関連する範囲に対応するように設計されたデータ構造が必要となりますので、入力値に基づいて一意のメモリ位置に到達するように設計されていることであり、そして同時に正確に各区間を更新
私はあなたを助けることができるリストに(または平衡二分木)をスキップだと思います。彼らはO(n)の中でルックアップを実行することはできませんが、彼らは木よりも、対数、まだ速く行うことができます。
私は、これは私が.NET BCLはすでに、このようなクラスが含まれていることを言うことができないので、あなたは残念ながら1を自分で実装するか、あなたのためにそれをサポートしているサードパーティのアセンブリを見つける必要があります適切な答えではありません知っています。しかし、こっちの CodeProjectので良い例があるようです。
私は以下の書いたコードを試すことができます。それゆえリスト/アレイが事前ソートさと仮定して、二分探索を使用します。
public static class ListExtensions
{
public static int GetAtMostIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer)
{
return GetAtMostIndex(list, value, comparer, 0, list.Count);
}
public static int GetAtLeastIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer)
{
return GetAtLeastIndex(list, value, comparer, 0, list.Count);
}
public static int GetAtMostIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer, int index, int count)
{
if (count == 0)
{
return -1;
}
int startIndex = index;
int endIndex = index + count - 1;
int middleIndex = 0;
int compareResult = -1;
while (startIndex < endIndex)
{
middleIndex = (startIndex + endIndex) >> 1; // / 2
compareResult = comparer.Invoke(list[middleIndex], value);
if (compareResult > 0)
{
endIndex = middleIndex - 1;
}
else if (compareResult < 0)
{
startIndex = middleIndex + 1;
}
else
{
return middleIndex;
}
}
if (startIndex == endIndex)
{
compareResult = comparer.Invoke(list[startIndex], value);
if (compareResult <= 0)
{
return startIndex;
}
else
{
int returnIndex = startIndex - 1;
if (returnIndex < index)
{
return -1;
}
else
{
return returnIndex;
}
}
}
else
{
//todo: test
return startIndex - 1;
}
}
public static int GetAtLeastIndex<TItem, TValue>(/*this*/ IList<TItem> list, TValue value, Func<TItem, TValue, int> comparer, int index, int count)
{
if (count == 0)
{
return -1;
}
int startIndex = index;
int endIndex = index + count - 1;
int middleIndex = 0;
int compareResult = -1;
while (startIndex < endIndex)
{
middleIndex = (startIndex + endIndex) >> 1; // / 2
compareResult = comparer.Invoke(list[middleIndex], value);
if (compareResult > 0)
{
endIndex = middleIndex - 1;
}
else if (compareResult < 0)
{
startIndex = middleIndex + 1;
}
else
{
return middleIndex;
}
}
if (startIndex == endIndex)
{
compareResult = comparer.Invoke(list[startIndex], value);
if (compareResult >= 0)
{
return startIndex;
}
else
{
int returnIndex = startIndex + 1;
if (returnIndex >= index + count)
{
return -1;
}
else
{
return returnIndex;
}
}
}
else
{
return endIndex + 1;
}
}
}
Kに最も近い見つけます:
dict.Keys.Where(i => i >= K).OrderBy(i => i).First();
またははるかに速います:
public int? GetNearestKey(dict, K)
{
int? lowerK = null;
foreach (int key in dict.Keys)
{
if (key == K)
{
lowerK = K;
break;
}
else if (key >= K && (!lowerK.HasValue || key < lowerK))
{
lowerK = key;
}
}
return lowerK;
}
があり、ベースのフレームワークでのバイナリ検索ツリーのコレクションの実装はありませんので、あなたは1を構築したり、実装を見つける必要がありますどちらか。あなたが述べたように、SortedListのは、検索の観点から最も近いですが、挿入/削除のために(その基本となる配列の実装による)遅います。
いと思いますが、間違いについて SortedList 複雑になります。
SortedList はO(log(n))償却の複雑さのために 挿入 新しい商品です。場合は事前にお知らの力でO(Log(n))最悪の場合には、
次の拡張メソッドでSortedSet<T>
のためにこれを行うことができます:
public static class SortedSetExtensions
{
public static bool FindLowerOrEqualThan<T>(this SortedSet<T> set, T value, out T first)
{
if(set.Count == 0)
{
first = default(T);
return false;
}
var minimum = set.Min;
if(set.Comparer.Compare(minimum, value) > 0)
{
first = default(T);
return false;
}
first = set.GetViewBetween(minimum, value).Max;
return true;
}
public static bool FindGreaterOrEqualThan<T>(this SortedSet<T> set, T value, out T first)
{
if (set.Count == 0)
{
first = default(T);
return false;
}
var maximum = set.Max;
if (set.Comparer.Compare(maximum, value) < 0)
{
first = default(T);
return false;
}
first = set.GetViewBetween(value, maximum).Min;
return true;
}
}