Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 26.11.02 10:24
Оценка:
Проблема такая — мне нужно написать процедуру, в которой бы на вход подавался какой-то список, а выход она подавала этот список уже отсортированным методом MergeSort (прямого слияния).
Сам алгоритм сортировки обычного численного массива у меня есть, проблема в другом — незнаю как переделать его (алгоритм) так, чтобы он сортировал список.
Re: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Кодт Россия  
Дата: 26.11.02 10:57
Оценка:
Здравствуйте, Ozone, Вы писали:

O>Проблема такая — мне нужно написать процедуру, в которой бы на вход подавался какой-то список, а выход она подавала этот список уже отсортированным методом MergeSort (прямого слияния).

O>Сам алгоритм сортировки обычного численного массива у меня есть, проблема в другом — незнаю как переделать его (алгоритм) так, чтобы он сортировал список.

Кажется, так:
typedef std::list<int> intlist;
typedef intlist::iterator iter;

void sort(intlist& data, iter begin, iter end)
{
  // [begin,end)
  if(begin == end) return; // 0 элементов
  end--;
  // [begin,end]
  if(begin == end) return; // 1 элемент
  end++;
  // [begin,end)

  // разбить список пополам
  iter m1 = begin, m2 = end;
  while(true)
  {
    if(m1 == m2) break;
    m1++;
    if(m1 == m2) break;
    m2--;
  }
  // m1 == m2

  // отсортировать под-интервалы
  sort(data, begin, m1); // [begin, m)
  sort(data, m1, end); // [m, end)

  // слияние
  while(begin != m1 && m1 != end)
  {
    if(*begin < *m1)
      begin++;
    else
    {
      m2 = m1;
      do { m2++; } while(m2 != end && *m2 < *begin);
      // перенести [m1,m2) перед begin
      data.splice(begin, data, m1, m2);
      m1 = m2;
    }
  }
}

(требует проверки!)
Перекуём баги на фичи!
Re: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Atilla Россия  
Дата: 26.11.02 10:58
Оценка:
Здравствуйте, Ozone, Вы писали:

O>Проблема такая — мне нужно написать процедуру, в которой бы на вход подавался какой-то список, а выход она подавала этот список уже отсортированным методом MergeSort (прямого слияния).

O>Сам алгоритм сортировки обычного численного массива у меня есть, проблема в другом — незнаю как переделать его (алгоритм) так, чтобы он сортировал список.

ну тогда какие проблемы? Вместо увеличения счетчиков цикла на 1, надо переставлять итераторы.
Кр-ть — с.т.
Re[2]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 26.11.02 11:00
Оценка:
Здравствуйте, Atilla, Вы писали:

A>ну тогда какие проблемы? Вместо увеличения счетчиков цикла на 1, надо переставлять итераторы.


Извините, я наверное вообще не смыслю в программировании, а это как?
Re[2]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 26.11.02 11:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Кажется, так:

К>
К>typedef std::list<int> intlist;
К>typedef intlist::iterator iter;

К>void sort(intlist& data, iter begin, iter end)
К>{
К>  // [begin,end)
К>  if(begin == end) return; // 0 элементов
К>  end--;
К>  // [begin,end]
К>  if(begin == end) return; // 1 элемент
К>  end++;
К>  // [begin,end)

К>  // разбить список пополам
К>  iter m1 = begin, m2 = end;
К>  while(true)
К>  {
К>    if(m1 == m2) break;
К>    m1++;
К>    if(m1 == m2) break;     ?????????????
К>    m2--;
К>  }
К>  // m1 == m2

К>  // отсортировать под-интервалы
К>  sort(data, begin, m1); // [begin, m)
К>  sort(data, m1, end); // [m, end)

К>  // слияние
К>  while(begin != m1 && m1 != end)
К>  {
К>    if(*begin < *m1)
К>      begin++;
К>    else
К>    {
К>      m2 = m1;
К>      do { m2++; } while(m2 != end && *m2 < *begin);
К>      // перенести [m1,m2) перед begin
К>      data.splice(begin, data, m1, m2);
К>      m1 = m2;
К>    }
К>  }
К>}
К>

К>(требует проверки!)
??? У вас 2 одинаковых условия в цикле while(true). Так и должно быть?
Re[3]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Atilla Россия  
Дата: 26.11.02 11:09
Оценка:
Здравствуйте, Ozone, Вы писали:

O>Извините, я наверное вообще не смыслю в программировании, а это как?


Тогда мой Вам совет: купите книгу Вирта "Алгоритмы и структуры данных" и внимательно прочтите. Там во-первых, описан этот алгоритм, во-вторых, будете немного смыслить в программировании.
Кр-ть — с.т.
Re[4]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 26.11.02 11:14
Оценка:
Здравствуйте, Atilla, Вы писали:

A>Здравствуйте, Ozone, Вы писали:


O>>Извините, я наверное вообще не смыслю в программировании, а это как?


A>Тогда мой Вам совет: купите книгу Вирта "Алгоритмы и структуры данных" и внимательно прочтите. Там во-первых, описан этот алгоритм, во-вторых, будете немного смыслить в программировании.


Я как раз думал об этом. Надо исправлять положение.
Re[3]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Кодт Россия  
Дата: 26.11.02 11:29
Оценка:
Здравствуйте, Ozone, Вы писали:

O>Здравствуйте, Кодт, Вы писали:


К>>
К>>  // разбить список пополам
К>>  iter m1 = begin, m2 = end;
К>>  while(true)
К>>  {
К>>    if(m1 == m2) break;
К>>    m1++;
К>>    if(m1 == m2) break;     ?????????????
К>>    m2--;
К>>  }
К>>  // m1 == m2
К>>

O>??? У вас 2 одинаковых условия в цикле while(true). Так и должно быть?
Да. Все правильно.

Идея такая: отступаем от начала и от конца на одинаковое расстояние.
Если сделать
while(m1 < m2)

то операция сравнения итераторов отнимет O(N^2) времени.

Если же проверять неравенство
while(m1 != m2)
{
  m1++; m2--;
}

то, при нечетном количестве элементов [m1,m2) итераторы перескочат друг через друга.

Поэтому сначала делаем один шаг вперед (и проверяем), затем другой шаг назад (и еще раз проверяем).

Поскольку изначально m1 != m2 (begin != end), то зайти в цикл мы должны (while(true)).
А поскольку за каждый шаг (m1++ | m2--) диапазон [m1,m2) сокращается на 1, то цикл гарантированно закончится за N проверок (где N — количество элементов).
Перекуём баги на фичи!
Re[4]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 27.11.02 07:06
Оценка:
Здравствуйте, Кодт, Вы писали:

Все вроде правильно по алгоритму, но только компилятор у меня выдает ошибки на этих строках:
typedef std::list<int> intlist;
typedef intlist::iterator iter;
Re[5]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Кодт Россия  
Дата: 27.11.02 07:48
Оценка:
Здравствуйте, Ozone, Вы писали:

O>Все вроде правильно по алгоритму, но только компилятор у меня выдает ошибки на этих строках:

O> typedef std::list<int> intlist;
O> typedef intlist::iterator iter;

#include <list> ?
Перекуём баги на фичи!
Re[6]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 27.11.02 09:25
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Ozone, Вы писали:


O>>Все вроде правильно по алгоритму, но только компилятор у меня выдает ошибки на этих строках:

O>> typedef std::list<int> intlist;
O>> typedef intlist::iterator iter;

К>#include <list> ?


???list??? Написал. Си говорит, что мол нет такого. Как быть?
Re[7]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Кодт Россия  
Дата: 27.11.02 09:53
Оценка:
Здравствуйте, Ozone, Вы писали:

К>>#include <list> ?


O>???list??? Написал. Си говорит, что мол нет такого. Как быть?


Во-первых, Си++.
Во вторых (проверь), именно <list>, а не <list.h>
В-третьих, убедись, что среди INCLUDE есть файлы библиотеки STL (это C++ — хедеры без расширения .h).

В-четвертых, ну, я не знаю, что еще может быть
Перекуём баги на фичи!
Re[8]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 27.11.02 10:01
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Ozone, Вы писали:


К>>>#include <list> ?


O>>???list??? Написал. Си говорит, что мол нет такого. Как быть?


К>Во-первых, Си++.

К>Во вторых (проверь), именно <list>, а не <list.h>
К>В-третьих, убедись, что среди INCLUDE есть файлы библиотеки STL (это C++ — хедеры без расширения .h).

К>В-четвертых, ну, я не знаю, что еще может быть


Перечислите пжлст, что нужно подключить (если можно — все)
Сильно буду благодарен
Re: Метод прямого слияния (MergeSort) - heeeelp!!!
От: earthling  
Дата: 27.11.02 10:26
Оценка:
А STL'овский stable_sort() — это какой алгоритм ? Мне сильно кажется, что MergeSort ..
Re[8]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Ozone Россия  
Дата: 27.11.02 10:44
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Во-первых, Си++.

К>Во вторых (проверь), именно <list>, а не <list.h>
К>В-третьих, убедись, что среди INCLUDE есть файлы библиотеки STL (это C++ — хедеры без расширения .h).

К>В-четвертых, ну, я не знаю, что еще может быть


Не могли бы Вы привести мне полный список того, что нужно включать в программу.
Заранее большое спасибо.
Re[9]: Метод прямого слияния (MergeSort) - heeeelp!!!
От: Кодт Россия  
Дата: 27.11.02 11:26
Оценка:
Здравствуйте, Ozone, Вы писали:

<>

Заодно и один баг исправил

// sorttest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <list>
#include <iostream>
using namespace std;

typedef list<int> intlist;
typedef intlist::iterator iter;

void dump(intlist& data, iter i1, iter i2)
{
    iter b = data.begin();
    iter e = data.end();
    
    cout << "{";

    while(true)
    {
        if(b == i1 && b == i2)
            cout << "|";
        else if(b == i1)
            cout << "[";
        else if(b == i2)
            cout << "]";
        else
            cout << " ";

        if(b == e)
            break;

        cout << *b;
        b++;
    }
    cout << "}";
}

void msort(int depth, intlist& data, iter begin, iter end)
{
    // [begin,end)
    if(begin == end) return; // 0 элементов
    end--;
    // [begin,end]
    if(begin == end) return; // 1 элемент
    end++;
    // [begin,end)
    
    cout << depth << " msort. ";
    dump(data, begin, end);
    cout << endl;

    // разбить список пополам
    iter m1 = begin, m2 = end;
    while(true)
    {
        if(m1 == m2) break;
        m1++;
        if(m1 == m2) break;
        m2--;
    }
    // m1 == m2

    cout << depth << " middle ";
    dump(data, m1, m2);
    cout << endl;

    // отсортировать под-списки
    iter m0;    

    m0 = begin; m0--; // запомнить итератор ПЕРЕД сортируемым участком (иначе он уплывет)
    msort(depth+1, data, begin, m1); // [begin, m)
    begin = m0; begin++; // и восстановить

    m0 = m1; m0--; // то же самое
    msort(depth+1, data, m1, end); // [m, end)
    m1 = m0; m1++;

    cout << depth << " merge: ";
    dump(data, begin, end);
    cout << endl;

    // слияние

    m0 = begin; m0--; // для отладочных целей :)

    while(begin != m1 && m1 != end)
    {
        cout << depth << " step   ";
        dump(data, begin, end);

        if(*begin < *m1)
        {
            cout << " skip";
            begin++;
        }
        else
        {
            cout << " splice";

            m2 = m1;
            // найдем фрагмент для перемещения
            do { m2++; } while(m2 != end && *m2 < *begin);
            // переместим его
            data.splice(begin, data, m1, m2);
            // восстановим указатель (m2 остался на месте; begin - после перемещенного фрагмента)
            m1 = m2;
        }

        cout << endl;
    }

    begin = m0; begin++; // восстановим, чтобы красиво распечатать

    cout << depth << " sorted ";
    dump(data, begin, end);
    cout << endl;   
}


int main(int argc, char* argv[])
{
    intlist data;
    int i;
    for(i = 8; i > 0; i--)  data.push_back(i);

    msort(1, data, data.begin(), data.end());

    return 0;
}


1 msort. {[8 7 6 5 4 3 2 1]}
1 middle { 8 7 6 5|4 3 2 1 }
2 msort. {[8 7 6 5]4 3 2 1 }
2 middle { 8 7|6 5 4 3 2 1 }
3 msort. {[8 7]6 5 4 3 2 1 }
3 middle { 8|7 6 5 4 3 2 1 }
3 merge: {[8 7]6 5 4 3 2 1 }
3 step   {[8 7]6 5 4 3 2 1 } splice
3 sorted {[7 8]6 5 4 3 2 1 }
3 msort. { 7 8[6 5]4 3 2 1 }
3 middle { 7 8 6|5 4 3 2 1 }
3 merge: { 7 8[6 5]4 3 2 1 }
3 step   { 7 8[6 5]4 3 2 1 } splice
3 sorted { 7 8[5 6]4 3 2 1 }
2 merge: {[7 8 5 6]4 3 2 1 }
2 step   {[7 8 5 6]4 3 2 1 } splice
2 sorted {[5 6 7 8]4 3 2 1 }
2 msort. { 5 6 7 8[4 3 2 1]}
2 middle { 5 6 7 8 4 3|2 1 }
3 msort. { 5 6 7 8[4 3]2 1 }
3 middle { 5 6 7 8 4|3 2 1 }
3 merge: { 5 6 7 8[4 3]2 1 }
3 step   { 5 6 7 8[4 3]2 1 } splice
3 sorted { 5 6 7 8[3 4]2 1 }
3 msort. { 5 6 7 8 3 4[2 1]}
3 middle { 5 6 7 8 3 4 2|1 }
3 merge: { 5 6 7 8 3 4[2 1]}
3 step   { 5 6 7 8 3 4[2 1]} splice
3 sorted { 5 6 7 8 3 4[1 2]}
2 merge: { 5 6 7 8[3 4 1 2]}
2 step   { 5 6 7 8[3 4 1 2]} splice
2 sorted { 5 6 7 8[1 2 3 4]}
1 merge: {[5 6 7 8 1 2 3 4]}
1 step   {[5 6 7 8 1 2 3 4]} splice
1 sorted {[1 2 3 4 5 6 7 8]}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.