示例#1
0
        ///// <summary>
        ///// Фаза слияния, сливаем из двух источников в один документ, попутно получая сортированный фазы длинной step * 2
        ///// </summary>
        ///// <param name="readerOne">Первый источник</param>
        ///// <param name="readerTwo">Второй источник</param>
        ///// <param name="writer">получатель</param>
        ///// <param name="step">Длина исходной сортированной фазы</param>
        private void Merge(StudentXmlReader readerOne, StudentXmlReader readerTwo, StudentXmlWriter writer, long step)
        {
            while (true)
            {
                if (!readerOne.IsCanRead && !readerTwo.IsCanRead)
                {
                    return;
                }

                DoPhase(readerOne, readerTwo, writer, step);
            }
        }
示例#2
0
        private void FillRest(long step, StudentXmlReader reader, StudentXmlWriter writer, Student student)
        {
            var     localStep    = step;
            Student?localStudent = student;

            while (localStudent.HasValue)
            {
                writer.Write(localStudent.Value);
                localStep--;
                localStudent = ReadNextStudentInPhase(localStep, reader, null);
            }
        }
示例#3
0
 /// <summary>
 /// Фаза разделения, разделяем данный на два файла по сортированным фазам длинной step
 /// </summary>
 /// <param name="reader">Источник</param>
 /// <param name="writerOne">Первый получатель</param>
 /// <param name="writerTwo">Второй получатель</param>
 /// <param name="step">Длина сортированной фазы</param>
 private void Devision(StudentXmlReader reader, StudentXmlWriter writerOne, StudentXmlWriter writerTwo, long step)
 {
     while (reader.IsNext())
     {
         writerOne.Write(reader.Current);
         for (long i = 1; (i < step) && reader.IsNext(); i++)
         {
             writerOne.Write(reader.Current);
         }
         for (long i = 0; (i < step) && reader.IsNext(); i++)
         {
             writerTwo.Write(reader.Current);
         }
     }
 }
示例#4
0
        /// <summary>
        /// Сортировка двухпутевого слияния Источник → https://prog-cpp.ru/sort-merge/
        /// Исходная последовательность разбивается на две подпоследовательности:
        ///Двухпутевое слияние
        ///Исходная последовательность разбивается на две подпоследовательности:
        ///Эти две подпоследовательности объединяются в одну, содержащую упорядоченные пары.
        ///Полученная последовательность снова разбивается на две, и пары объединяются в упорядоченные четверки:
        ///Полученная последовательность снова разбивается на две и собирается в упорядоченные восьмерки.
        ///Данная операция повторяется до тех пор, пока полученная упорядоченная последовательность не будет иметь такой же размер, как у сортируемой.
        /// </summary>
        /// <param name="path">Путь к файлу</param>
        public void Sort(string path)
        {
            //Длинна отсортированной фазы
            var lengthFase = 1L;
            //Счетчик количества проходов
            int count = 0;

            while (true)
            {
                count++;
                //Разделение
                using (var reader = new StudentXmlReader(path))
                {
                    using (var writerOne = new StudentXmlWriter(FirstFilename))
                    {
                        using (var writerTwo = new StudentXmlWriter(SecondFilename))
                        {
                            Devision(reader, writerOne, writerTwo, lengthFase);
                        }
                    }
                }


                //140 байт - это начальные теги xml
                using (var l = new FileStream(SecondFilename, FileMode.Open))
                {
                    if (l.Length < 200)
                    {
                        break;
                    }
                }

                //Слияние
                using (var writer = new StudentXmlWriter(path))
                {
                    using (var readerOne = new StudentXmlReader(FirstFilename))
                    {
                        using (var readerTwo = new StudentXmlReader(SecondFilename))
                        {
                            Merge(readerOne, readerTwo, writer, lengthFase);
                        }
                    }
                }

                lengthFase *= 2;
            }
        }
示例#5
0
        private void DoPhase(StudentXmlReader readerOne, StudentXmlReader readerTwo, StudentXmlWriter writer, long step)
        {
            var stepOne = step;
            var stepTwo = step;

            Student?currentFirst  = null;
            Student?currentSecond = null;

            while (true)
            {
                currentFirst  = ReadNextStudentInPhase(stepOne, readerOne, currentFirst);
                currentSecond = ReadNextStudentInPhase(stepTwo, readerTwo, currentSecond);

                if (!currentFirst.HasValue && !currentSecond.HasValue)
                {
                    return;
                }

                if (!currentFirst.HasValue && currentSecond.HasValue)
                {
                    FillRest(stepTwo, readerTwo, writer, currentSecond.Value);
                    return;
                }

                if (currentFirst.HasValue && !currentSecond.HasValue)
                {
                    FillRest(stepOne, readerOne, writer, currentFirst.Value);
                    return;
                }

                if (currentFirst.Value.CompareTo(currentSecond.Value) > 0)
                {
                    writer.Write(currentSecond.Value);
                    stepTwo--;
                    currentSecond = null;
                }
                else
                {
                    writer.Write(currentFirst.Value);
                    stepOne--;
                    currentFirst = null;
                }
            }
        }