예제 #1
0
        private IEnumerable <long> BinarySearchAll(long start, long number, int key, object sample)
        {
            if (number < plain)
            {
                return(keyoffsets.ElementValues(keyoffsets.ElementOffset(start), number)
                       .Where(pair => DoubleComp((object[])pair, key, sample) == 0)
                       .Select(pair => (long)((object[])pair)[1])
                       );
            }
            long half = number / 2;

            if (half == 0)
            {
                // Получаем пару (ключ-офсет)
                object[] pair = (object[])keyoffsets.GetByIndex(start);
                int      cmp  = DoubleComp(pair, key, sample);
                if (cmp == 0)
                {
                    return(Enumerable.Repeat <long>((long)pair[1], 1));
                }
                else
                {
                    return(Enumerable.Empty <long>()); // Не найден
                }
            }

            long middle = start + half;
            long rest   = number - half - 1;

            object[] mid_pair     = (object[])keyoffsets.GetByIndex(middle);
            var      middle_depth = DoubleComp(mid_pair, key, sample);

            if (middle_depth == 0)
            { // Вариант {левый, центральная точка, возможно правый}
                IEnumerable <long> flow = BinarySearchAll(start, half, key, sample).Concat(Enumerable.Repeat <long>((long)mid_pair[1], 1));
                if (rest > 0)
                {
                    return(flow.Concat(BinarySearchAll(middle + 1, rest, key, sample)));
                }
                else
                {
                    return(flow);
                }
            }
            if (middle_depth < 0)
            {
                if (rest > 0)
                {
                    return(BinarySearchAll(middle + 1, rest, key, sample));
                }
                else
                {
                    return(Enumerable.Empty <long>());
                }
            }
            else
            {
                return(BinarySearchAll(start, half, key, sample));
            }
        }
예제 #2
0
        private IEnumerable <long> GetAllByKey(long start, long number, int key)
        {
            if (number < plain)
            {
                return(keyoffsets.ElementValues(keyoffsets.ElementOffset(start), number)
                       .Where(pair => (int)((object[])pair)[0] == key)
                       .Select(pair => (long)((object[])pair)[1]));
            }
            long half = number / 2;

            if (half == 0)
            {
                // Получаем пару (ключ-офсет)
                object[] pair = (object[])keyoffsets.GetByIndex(start);
                int      cmp  = ((int)pair[0]).CompareTo(key);
                if (cmp == 0)
                {
                    return(Enumerable.Repeat <long>((long)pair[1], 1));
                }
                else
                {
                    return(Enumerable.Empty <long>()); // Не найден
                }
            }

            long middle = start + half;
            long rest   = number - half - 1;

            object[] mid_pair     = (object[])keyoffsets.GetByIndex(middle);
            var      middle_depth = ((int)mid_pair[0]).CompareTo(key);

            if (middle_depth == 0)
            { // Вариант {левый, центральная точка, возможно правый}
                IEnumerable <long> flow = GetAllByKey(start, half, key).Concat(Enumerable.Repeat <long>((long)mid_pair[1], 1));
                if (rest > 0)
                {
                    return(flow.Concat(GetAllByKey(middle + 1, rest, key)));
                }
                else
                {
                    return(flow);
                }
            }
            if (middle_depth < 0)
            {
                if (rest > 0)
                {
                    return(GetAllByKey(middle + 1, rest, key));
                }
                else
                {
                    return(Enumerable.Empty <long>());
                }
            }
            else
            {
                return(GetAllByKey(start, half, key));
            }
        }
예제 #3
0
        public void Scan(Func <long, object, bool> handler)
        {
            long ll = sequence.Count();

            if (ll == 0)
            {
                return;
            }
            for (long ii = 0; ii < ll; ii++)
            {
                long     off         = ii == 0 ? sequence.ElementOffset(0) : sequence.ElementOffset();
                object[] full_object = (object[])sequence.GetElement(off);
                if ((bool)full_object[0])
                {
                    continue;                       // если уничтожен
                }
                bool ok = handler(off, full_object[1]);
                if (!ok)
                {
                    break;
                }
            }
        }
예제 #4
0
        private object[] rare_elements = null; // --


        public void Build()
        {
            // Формируем последовательность offset_sequ
            offset_sequ.Clear();
            bearing.Scan((off, obj) =>
            {
                bool isapp = applicable(obj);
                if (applicable(obj))
                {
                    offset_sequ.AppendElement(off);
                }
                return(true);
            });
            offset_sequ.Flush();
            // Возможно, нам понадобятся два дополнительных стрима
            FileStream tmp_stream1 = null;
            FileStream tmp_stream2 = null;

            // Определяем рекурсивный метод построения Bld(long start_ind, long number) который в итоге переупорядочивает
            // отрезок последовательности offset_sequ так, что ссылаемые элементы становятся отсортированными.
            void Bld(long start_ind, long number)
            {
                if (number <= volume_of_offset_array)
                {
                    long[]   offsets  = new long[number];
                    object[] elements = new object[number];
                    // берем в массивы
                    for (long i = 0; i < number; i++)
                    {
                        long off = (long)offset_sequ.GetByIndex(start_ind + i);
                        offsets[i]  = off;
                        elements[i] = bearing.GetItem(off);
                    }
                    // Сортируем
                    Array.Sort(elements, offsets, comp_default);
                    // кладем из массивов в последовательность
                    for (long i = 0; i < number; i++)
                    {
                        if (i == 0)
                        {
                            offset_sequ.SetElement(offsets[i], offset_sequ.ElementOffset(start_ind));
                        }
                        else
                        {
                            offset_sequ.SetElement(offsets[i]);
                        }
                    }
                }
                else
                {
                    // надо разбить отрезок на два, в каждом сделать сортировку, а результаты слить.
                    long firsthalf_start   = start_ind;
                    long firsthalf_number  = number / 2;
                    long secondhalf_start  = start_ind + firsthalf_number;
                    long secondhalf_number = number - firsthalf_number;

                    Bld(firsthalf_start, firsthalf_number);
                    Bld(secondhalf_start, secondhalf_number);

                    if (tmp_stream1 == null)
                    {
                        tmp_stream1 = File.Open(tmpdir + "tmp1.$$$", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    }
                    if (tmp_stream2 == null)
                    {
                        tmp_stream2 = File.Open(tmpdir + "tmp2.$$$", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    }
                    tmp_stream1.Position = 0L;
                    tmp_stream2.Position = 0L;

                    byte[] buffer = new byte[buffersize];

                    Stream source1 = offset_sequ.Media;
                    source1.Position = 8 + firsthalf_start * 8;
                    long nbytes1 = firsthalf_number * 8;
                    while (nbytes1 > 0)
                    {
                        int nb = source1.Read(buffer, 0, nbytes1 >= buffer.Length ? buffer.Length : (int)nbytes1);
                        tmp_stream1.Write(buffer, 0, nb);
                        nbytes1 -= nb;
                    }
                    Stream source2 = offset_sequ.Media;
                    source2.Position = 8 + secondhalf_start * 8;
                    long nbytes2 = secondhalf_number * 8;
                    while (nbytes2 > 0)
                    {
                        int nb = source2.Read(buffer, 0, nbytes2 >= buffer.Length ? buffer.Length : (int)nbytes2);
                        tmp_stream2.Write(buffer, 0, nb);
                        nbytes2 -= nb;
                    }
                    tmp_stream1.Position = 0L;
                    BinaryReader br1  = new BinaryReader(tmp_stream1);
                    long         off1 = br1.ReadInt64();
                    object       obj1 = bearing.GetItem(off1);
                    long         nom1 = 0; // номер обрабатываемого элемента
                    tmp_stream2.Position = 0L;
                    BinaryReader br2     = new BinaryReader(tmp_stream2);
                    long         off2    = br2.ReadInt64();
                    object       obj2    = bearing.GetItem(off2);
                    long         nom2    = 0; // номер обрабатываемого элемента
                    long         out_ind = start_ind;
                    while (nom1 < firsthalf_number && nom2 < secondhalf_number)
                    {
                        if (comp_default.Compare(obj1, obj2) <= 0)
                        {
                            offset_sequ.SetElement(off1, offset_sequ.ElementOffset(out_ind));
                            nom1++;
                            if (nom1 < firsthalf_number)
                            {
                                off1 = br1.ReadInt64();
                                obj1 = bearing.GetItem(off1);
                            }
                        }
                        else
                        {
                            offset_sequ.SetElement(off2, offset_sequ.ElementOffset(out_ind));
                            nom2++;
                            if (nom2 < secondhalf_number)
                            {
                                off2 = br2.ReadInt64();
                                obj2 = bearing.GetItem(off2);
                            }
                        }
                        out_ind++;
                    }
                    // Перепись остатков
                    if (nom1 < firsthalf_number)
                    {
                        for (long ii = nom1; ii < firsthalf_number; ii++)
                        {
                            if (ii != nom1)
                            {
                                off1 = br1.ReadInt64();
                            }
                            offset_sequ.SetElement(off1, offset_sequ.ElementOffset(out_ind));
                            out_ind++;
                        }
                    }
                    else if (nom2 < secondhalf_number)
                    {
                        for (long ii = nom2; ii < secondhalf_number; ii++)
                        {
                            if (ii != nom2)
                            {
                                off2 = br2.ReadInt64();
                            }
                            offset_sequ.SetElement(off2, offset_sequ.ElementOffset(out_ind));
                            out_ind++;
                        }
                    }
                }
            };

            // Исполним
            Bld(0L, offset_sequ.Count());

            if (tmp_stream1 != null)
            {
                tmp_stream1.Close();
                File.Delete(tmpdir + "tmp1.$$$");
            }
            if (tmp_stream2 != null)
            {
                tmp_stream2.Close();
                File.Delete(tmpdir + "tmp2.$$$");
            }
            Refresh();
        }