Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.12.2014, 12:05   #1
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию Рекурсивная сортировка слиянием

Сортирует массив используя рекурсивную сортировку слиянием
https://ru.wikipedia.org/wiki/Сортировка_слиянием
up - указатель на массив который нужно сортировать
down - указатель на массив с, как минимум, таким же размерои как у 'up', используется как буфер
left - левая граница массива, передайте 0 чтобы сортировать массив с начала
right - правая граница массива, передайте длинну массива - x чтобы сортировать массив до последнего элемента
возвращает: указатель на отсортированный массив. Из за особенностей работы
данной имплементации, отсортированная версия массива может оказаться либо в 'up' либо в 'down'

Код:
#include<iostream.h>
#include<stdlib>
using namespace std;

void Print(int *arr, int x)
{
  for(int i = 0; i < x; i++) cout << arr[i] << "  ";
  cout << "\n";
}

int* MergeSort(int *up, int *down, unsigned int left, unsigned int right)
{
  if (left == right)
  {
    down[left] = up[left];
    return down;
  }
  unsigned int middle = (unsigned int)((left + right)/2);// * 0.5f);
  // разделяй и сортируй
  int *l_buff = MergeSort(up, down, left, middle);
  int *r_buff = MergeSort(up, down, middle + 1, right);

  // слияние двух отсортированных половин
  int *target = l_buff == up ? down : up;

  unsigned int l_cur = left, r_cur = middle + 1;
  for (unsigned int i = left; i <= right; i++)
  {
    if (l_cur <= middle && r_cur <= right)
    {
      if (l_buff[l_cur] < r_buff[r_cur])
      {
        target[i] = l_buff[l_cur];
        l_cur++;
      }
      else
      {
        target[i] = r_buff[r_cur];
        r_cur++;
      }
    }
    else if (l_cur <= middle)
    {
      target[i] = l_buff[l_cur];
      l_cur++;
    }
    else
    {
      target[i] = r_buff[r_cur];
      r_cur++;
    }
  }
cout << "target  "; Print(target, middle);
//  cout << "l_buff  "; Print(l_buff, middle);
//  cout << "r_buff  "; Print(r_buff, middle);
  return target;
}

//----------------------------------------------

int main()
{
  cout << "рекурсивная сортировка слиянием. ";
  int x = 10;
  int *iarr = new int[x];
  iarr[0] = 63; iarr[1] = 64; iarr[2] = 5; iarr[3] = 65; iarr[4] = 50;
  iarr[5] = 62; iarr[6] = 53; iarr[7] = 54; iarr[8] = 60; iarr[9] = 61;
  int *buf = new int[x];
  int *rez = new int[x];
  rez = MergeSort(iarr, buf, 0, x);
  if(x <= 100) Print(rez, x+1);
  cout << "\n\n";

  delete iarr;

  system("pause");
  return 0;
}
Проблема в том, что алгоритм почему-то вставляет в отсортированную последовательность цифру, нигде в массиве не заданную. Если при выводе задать размер массива на единицу больше, за лишней цифрой оказывается нормально отсортированная последовательность.
Третий день голову ломаю, не могу понять в чём причина.
Изображения
Тип файла: jpg MergeSort1.jpg (41.5 Кб, 76 просмотров)
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Последний раз редактировалось Smitt&Wesson; 23.12.2014 в 12:15.
Smitt&Wesson вне форума Ответить с цитированием
Старый 23.12.2014, 12:20   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

Выход за границу массива.
При первоначальном вызове MergeSort последний аргумент - количество элементов (10) а должен быть индекс последнего элемента (9)
waleri вне форума Ответить с цитированием
Старый 23.12.2014, 13:15   #3
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Выход за границу массива.
При первоначальном вызове MergeSort последний аргумент - количество элементов (10) а должен быть индекс последнего элемента (9)
Ну, это я давно уже понял (отладчиком умею пользоваться). Вопрос в том, как это устранить не нарушая работу всего алгоритма? Статья в Вики, откуда я эту прогу слизал, ответов на этот вопрос не даёт.

Ответ нашел. При вызове функции нужно задавать значение x-1.
rez = MergeSort(iarr, buf, 0, x-1);
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Последний раз редактировалось Smitt&Wesson; 23.12.2014 в 13:27.
Smitt&Wesson вне форума Ответить с цитированием
Старый 23.12.2014, 13:54   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

на входе (left перый сортируемый \right первый НЕсортируемый (следующий за последним!!)
на промежуточных
Код:
left первый сортируемый \ middle последний СОРТИРУЕМЫЙ 
midle+1 первый сортируемый    \ right первый НЕ сортируемый
РАЗНАЯ интерпретация параметра right !!!!

Код:
left первый сортируемый  \ middle первый НЕ сортируемый
middle  первый Сортируемый  \ right первый НЕ сортируемый
Условие выхода из рекурсии right (первый НЕсортируемый) - left (первый сортируемый) == 1

Цитата:
Ответ нашел. При вызове функции нужно задавать значение x-1.
Или сменить входную интерпретацию (последний сортируемый)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 23.12.2014 в 13:57.
evg_m вне форума Ответить с цитированием
Старый 23.12.2014, 14:49   #5
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
Или сменить входную интерпретацию (последний сортируемый)
Рекурсивная сортировеа Qsort, работает точно так же. При её вызове размер массива задаётся как x-1. Так, что это не принципиально.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[C++] Сортировка слиянием syxov Помощь студентам 0 26.09.2012 21:46
Сортировка слиянием. С++ Noizik Помощь студентам 1 09.05.2012 14:23
сортировка слиянием (C++) DarkAltair Помощь студентам 7 11.10.2011 21:12
Сортировка слиянием C++ PinkPink Помощь студентам 3 10.10.2011 22:44
СОРТИРОВКА СЛИЯНИЕМ spawn969 Помощь студентам 5 12.05.2011 01:03