문제

나는 일부를 변환하는 C++코드는 C#와 호출하는 std::도::lower_bound(k)항목을 찾을 수 없습니 맵에서는 키가 크거나 같다 k.그러나 나는 보지 않는 어떤 방법으로 같은 일을 할 수니다.NET 의 SortedDictionary.가 열 수 있을 구현하는 해결 방법을 사용하여 다음 코드 예제에서는 만들,그러나 불행하게도 다음 코드 예제에서는 만들이 너무 느리(O(n)삽입과 삭제키).내가 무엇을 할 수 있습니까?

참고:내가 찾을 사용하여 해결 방법을 활용하는 내 특정 시나리오...특히,내 키에는 인구 밀도의 정수에서 시작 단 0 다,그래서 내가 사용하는 목록<TValue> 내 사전에 목록으로 인덱스로 봉사하고 열쇠이고,검색 키 보다 크거나 k 에서 할 수 있는 몇 루프 반복.하지만 여전히 좋은 것을 보 원래의 질문에 대답합니다.

도움이 되었습니까?

해결책 4

내가 만들어진 세 개의 데이터 구조와 관련된 B+나무는 이 기능을 제공한 모든 데이터 유형: BList<T>, BDictionary<K,V>BMultiMap<K,V>.이러한 각 데이터 구조를 제공 FindLowerBound()FindUpperBound() 작동하는 방법은 다음과 같 C++'s lower_boundupper_bound.

다른 팁

그것은 몇 개월 동안의 일을,그러나 마지막에 나에서 제공 할 수 있습니다 적어도 부분적인 해결책을 이 문제는...나는 그것을 컴팩트 패트리샤 라,정렬된 사전이 제공하는"다음 찾기 더 큰 키는"작업입니다.

http://www.codeproject.com/KB/recipes/cptrie.aspx

그것은 단지 부분적인 해결책은 이후 특정 종류의 키 지원,즉 byte[], string, 며,모든 기본 정수 유형(Int8..UInt64).또한,문자열 정렬은 대소문자를 구분합니다.

문제는 사전/해시 테이블은 설계에 도착하는 고유의 메모리 위치에 따라 입력 값,그래서 당신이 필요로 하는 데이터 구조은 범위를 수용 할 수 있도록 설계되어 관련된 각 값을 저장하고 동시에 업데이트 간격이 올바르

나는 생각한 skip 목록 (또는 균형 잡힌 이진 나무)은 당신을 도울 수 있습니다.하지만 그들을 수행할 수 없습니다 조회를 O(n),그들이 할 수있는 로그와 아직도보다 더 빨리 나무입니다.

내가 이것을 알고 있지 않은 적당한 답변 때문에 내가 말할 수 없습니다.NET BCL 이 이미 포함되어 이러한 클래스에,당신은 불행하게도를 구현해야 한 자 또는 제 3 자는 어셈블리를 지원합니다.가 있을 것이 좋은 예를 통해서 이 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;
}

이 없 검색 트리 컬렉션 구현을 기본 프레임워크,그래서 당신은 하나가 하나를 찾을 구현합니다.으로 지적하신 다음 코드 예제에서는 만들이 가장 가까운 측면에서 찾지만 느립(으로 인해 그것의 근본적인 배열 구현)삽입/삭제합니다.

제가 생각하기에서 실수가에 대한 질문에 대한 다음 코드 예제에서는 만들 복잡합니다.

다음 코드 예제에서는 만들 는 O(로그(n))상각에 대한 복잡성 삽입 새로운 항목입니다.당신이 사전에 알고 있는 용량에서 수행할 수 있습 O(로그(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;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top