Автор Тема: Склеивание двух кусков массива, соритрованных по возрастанию.  (Прочитано 4271 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Hitokiri_Rid

  • VIP
  • Ветеран
  • *****
  • Сообщений: 3422
  • Пол: Мужской
    • Просмотр профиля
Собственно в чем дело.
Допустим имеется два куска массива (равное кол-во элементов, если у массива нечетное число - то элемент относится к какому-нибудь куску). Оба куска отсортированы по возрастанию.
Нужно склеить из них один, тоже отсортированный по возрастанию.
В общем в чем сабж. В классике это делается с помощью дополнительного массива такой же размерности.
Нужен алгоритм, который для склеивания использует фиксированное число ячеек (без дополнительного массива).
Алгоритм должен обладать линейной трудоемкостью.
Все :).
« Последнее редактирование: 26.04.07, 21:23:37 от Mr.RID »
Fallit et attollit vires in milite causa.


Оффлайн LEO

  • Ветеран
  • *****
  • Сообщений: 4417
  • Карма: 310
  • Пол: Мужской
    • Просмотр профиля
> если у массива нечетное число - то элемент относится к какому-нибудь куску
какое еще число у массива?

> Алгоритм должен обладать линейной трудоемкостью.
написал бы что это...

2 счетчика, один перебирает эл-ты в одном массиве, другой - вдругом
цикл
if a(i)<=b(j)  then
  с(k)=a(i)
  k++
  i++
else
  c(k)=b(j)
  k++
  j++
end if
http://is.gd/fpTeSMПродам книжки про Ajax и ASP.NET, http://is.gd/lDL64HПриглашаю в Dropbox

Оффлайн Hitokiri_Rid

  • VIP
  • Ветеран
  • *****
  • Сообщений: 3422
  • Пол: Мужской
    • Просмотр профиля
> если у массива нечетное число - то элемент относится к какому-нибудь куску
какое еще число у массива?

Число элементов. :)

Трудоемкость - это число базовых операций, нужных для выполнения алгоритма.

Ты мне как раз привел пример с дополнительным массивом.
Мне нужно без него.
Fallit et attollit vires in milite causa.

Оффлайн LEO

  • Ветеран
  • *****
  • Сообщений: 4417
  • Карма: 310
  • Пол: Мужской
    • Просмотр профиля
> если у массива нечетное число - то элемент относится к какому-нибудь куску
какое еще число у массива?

Число элементов. :)

Трудоемкость - это число базовых операций, нужных для выполнения алгоритма.

Ты мне как раз привел пример с дополнительным массивом.
Мне нужно без него.
шо значит склеить тогда? ты мне скажи что в итоге должно получится?

в примере массив ц - итоговый, размерности а + б

....
или те надо в а и б так числа переставить, чтобы б было продолжением а?
.. ща думать неохота, а варинант, предложенный мной, потом половину массива ц записать в а, вторую - в б, и ц уничтожить - не прокактит?

.. в общем -то можешь взять любой алгоритм сортировки, и переделать его, как будто в исходе - 2 массива, типа если те надо ц отстртировать, и в нем н элементов, то переделываешь алгоритм так, что если рассматривается индекс меньше н\2 - берем массив а, если больше - б
зы. из простых алгоритмов имхо лучше всего вставки со сдвигом... хотя если вам не принципиально -  и минимакс сойдет. там строк менььше))
http://is.gd/fpTeSMПродам книжки про Ajax и ASP.NET, http://is.gd/lDL64HПриглашаю в Dropbox

Оффлайн LEO

  • Ветеран
  • *****
  • Сообщений: 4417
  • Карма: 310
  • Пол: Мужской
    • Просмотр профиля
Трудоемкость - это число базовых операций, нужных для выполнения алгоритма.
круто

а
линейной трудоемкостью что называют?! =)

ты хочешь сказать, что число сравнений\итераций или еще чего-то должно с увеличением размеров массивов увеличивать пропорционально, а не квадратично, как например в минимаксе??
ну могу сказать, что применая алгоримты с сортировкой, даже сложные, как хоара, слияний, или древовидной сортировки, минимум сравнений - все равно n*ln(n) ... но это уже намног лучше n*n ))
http://is.gd/fpTeSMПродам книжки про Ajax и ASP.NET, http://is.gd/lDL64HПриглашаю в Dropbox

Оффлайн Hitokiri_Rid

  • VIP
  • Ветеран
  • *****
  • Сообщений: 3422
  • Пол: Мужской
    • Просмотр профиля
В итоге должен получиться массив.
Чорт, я походу неправильно объяснил.
Есть массив, поделен пополам. Каждая половина отсортирована по возрастанию. Нужно, чтобы весь массив был отсортирован по возрастанию. Без использования дополнительного массива, с линейной трудоемкостью.

ты хочешь сказать, что число сравнений\итераций или еще чего-то должно с увеличением размеров массивов увеличивать пропорционально, а не квадратично, как например в минимаксе??

Ну, почти так. В алгоритме с доп массивом так и происходит. трудоемкость там имеет вид Fa(n)=c*n+b
c и b - коэффициенты, n - кол-во элементов массива.
« Последнее редактирование: 26.04.07, 23:48:50 от Mr.RID »
Fallit et attollit vires in milite causa.

Оффлайн LEO

  • Ветеран
  • *****
  • Сообщений: 4417
  • Карма: 310
  • Пол: Мужской
    • Просмотр профиля
2 счетчика, один перебирает эл-ты в одной половине, другой - вдругой
i<j
цикл

if с(j)<=с(i)  then
  // с сдвигаем вправо начиная с iго номера, в c(I) записываем c(j)
   j++
else
  i++
end if

че-то типа этого... дальше уже сам додумаешь)))
http://is.gd/fpTeSMПродам книжки про Ajax и ASP.NET, http://is.gd/lDL64HПриглашаю в Dropbox

Оффлайн Wizard

  • Ветеран
  • *****
  • Сообщений: 1861
  • Карма: -3
  • Пол: Мужской
    • Просмотр профиля
Сортировка слиянием это называется.
Вот стандартный алгоритм из любого учебника и взять

Оффлайн Hitokiri_Rid

  • VIP
  • Ветеран
  • *****
  • Сообщений: 3422
  • Пол: Мужской
    • Просмотр профиля
Сортировка слиянием это называется.
Вот стандартный алгоритм из любого учебника и взять

Для алгоритма сортировки слиянием требуется дополнительный массив. Ведь так?
LEO, твой алгоритм тоже не подходит.
Fallit et attollit vires in milite causa.

Оффлайн LEND

  • Пользователь
  • **
  • Сообщений: 95
  • Карма: 155
  • Истина как всегда где-то рядом
    • Просмотр профиля
Да, очень интересная задача.
Смотря как ее представить. Допустим есть общий массив A. Разобьем его на два массива 1 и 2.
Т.е. A=1+2
Допустим, что эти массивы уже отсортированы.
Пусть массив 1 состоит из 4 элементов 1,2,3,4
Пусть массив 2 состоит из 4 элементов 5,6,7,8

И вот здесь нужно эти массивы соеденить в один. Это сделать можно, но не во всех языках программирования. Некоторые языки программирования проверяют диапазон индексов.
Можно конечно эту проверку отключить и попробовать.
Я нашел удивительно интересное решение этой задачи с помощью TPASCAL. Там есть один оператор при помощи которого можно склеить два одинаковых по размерам массива в один. Это оператор MOVE, но потом я также нашел способ при котором можно обойтись и без него. Ведь вся проблема этой задачи - склеить два одинаковых по размерностям массива и все. И если даже они не отсортированы, то их можно отсортировать после того как они будут соеденены в один. Почему так - массивы могут быть представлены и таким
образом:
1 - 1,6,4,7
2 - 5,2,8,3

В этом случае хоть их и сортируй отдельно, все равно надо сортировать в общем массиве A. Мне лично удобно сортировать "пузырьковой сортировкой". Можете попробовать другую.
 
Привожу алгоритмы на TPASCAL

I вариант --- массивы 1 и 2 правильно отсортированы.

==================================================
uses crt;
var
  A : array[1..4] of integer;
  B : array[1..4] of integer;
  dla:integer;
  i:integer;
BEGIN
ClrScr;
A[1]:=1;
A[2]:=2;
A[3]:=3;
A[4]:=4;

B[1]:=5;
B[2]:=6;
B[3]:=7;
B[4]:=8;


dla:=4; {кол.элементов в каждом массиве}
        {4 в цикле i:=4 то же кол. элементов в массиве}

for i:=4 downto 1 do A[i+dla]:=B(i);  {Здесь у массива B квадратные скобки}
for i:=1 to 8 do write(A(i),' ');  {Здесь у массива A квадратные скобки}
writeln;
              (* Получаем 1 2 3 4 5 6 7 8 *)
writeln('Дальше - Enter');
READLN;
END.

==================================================

II вариант --- массивы 1 и 2 неотсортированы.
==================================================
uses crt;
var
  A : array[1..5] of integer; {1 массив}
  B : array[1..5] of integer; {2 массив}
  dla:integer;
  i,j:integer;
  men:integer;
    n:integer;
BEGIN
ClrScr;
A[1]:=5;
A[2]:=2;
A[3]:=8;
A[4]:=4;
A[5]:=10;

B[1]:=1;
B[2]:=6;
B[3]:=7;
B[4]:=3;
B[5]:=9;

dla:=5; {кол.элементов в каждом массиве}
        {5 в цикле i:=5 то же кол. элементов в массиве}

for i:=5 downto 1 do A[i+dla]:=B(i);      {Здесь у массива B квадратные скобки}
n:=10; {Общее кол. элементов в массиве}
{-------------- Сортируем массив -----------------}
for i:=1 to n-1 do begin
 for j:=1 to n-1 do begin
      if A[j+1]<=A[j] then begin
                           men:=A[j];
                           A[j]:=A[j+1];
                           A[j+1]:=men
                           end;
                     end;
                  end;
{-------------------------------------------------}
for i:=1 to 10 do write(A(i),' '); {Здесь у массива A квадратные скобки}
writeln;
              (* Получаем Массив A 1 2 3 4 5 6 7 8 9 10 *)
writeln('Дальше - Enter');
READLN;
END.

==================================================
Возможно это и есть какой то путь решения?
Зато ВЫ не применяете 3 массив и даже при сортировке.
Такую же задачу наверно возможно решить и в C/C++. Я не пробовал - не было времени.
Я эти два алгоритма проверял. У меня работают. Брал больше элементов - до 100, также работают. Программа сбоя не давала. Возможно, есть еще и другие варианты решения, но их надо искать.
Я привел легкий пример с незначительным количеством элементов в каждом массиве.


С уважением
LEND
В мире временном, сущность которого - тлен,
Не сдавайся вещам несущественным в плен. © О.Х.

Оффлайн Hitokiri_Rid

  • VIP
  • Ветеран
  • *****
  • Сообщений: 3422
  • Пол: Мужской
    • Просмотр профиля
Так мне и нужен алгоритм сортировки. Я же написал, что про склеивание попутал. Это один массив, из n элементов, поделен на n/2. Каждая половина отсортирована по возрастанию. Вот и надо отсортировать весь массив. Главное в задаче - линейная трудоемкость алгоритма сортировки. Сортировка пузырьком имеет трудоемкость, если мне память не изменяет, порядка квадрата.
Fallit et attollit vires in milite causa.

Оффлайн LEND

  • Пользователь
  • **
  • Сообщений: 95
  • Карма: 155
  • Истина как всегда где-то рядом
    • Просмотр профиля
Да, не увидел ВАШЕГО сообщения о сортировке.
Хорошо. Представим, что массив C поделен пополам. Первая и вторая половина его граммотно отсортирована.
Пусть 1 половина представлена следующими элементами 1 3 4 7
Пусть 2 половина представлена следующими элементами 2 5 6 8
Надо написать такой алгоритм который сортировал весь массив C
Также допустим:
Если 1-й элемент первой половины больше 1-го элемента второй половины, тогда исходным элементом отсчета будет 1-й элемент первой половины. Если наоборот, меняем местами первые элементы и также делаем исходным элементом отсчета 1-й элемент первой половины. 
Тогда:
 
1  2
3  5
4  6
7  8
 
Меняем 2 элемент 1-ой половины(3) на 1 элемент 2-ой половины(2) т.е. 3 и 2
меняем местами.
1 3
2 5
4 6
7 8

Меняем 3 элемент 1-ой половины(4) на 1 элемент 2-ой половины(3) т.е. 4 и 3
меняем местами.

1 4
2 5
3 6
7 8
и т.д.

Получаем отсортированный массив C
=======================================================
uses crt;
 const
  n=9;
var
  C:  array[1..n] of integer;
  j:integer;
  men:integer;
  pol:integer;
BEGIN
ClrScr;

C[1]:=1;
C[2]:=3;
C[3]:=4;
C[4]:=7;
C[5]:=2;
C[6]:=5;
C[7]:=6;
C[8]:=8;
C[9]:=9;



             pol:=n div 2; { Половина }
             if c[1]>c[pol+1] then begin
                                   men:=c[pol+1];
                                   c[pol+1]:=c[1];
                                   c[1]:=men;
                                   end;
                   men:=c[pol+1];

                   repeat
                    j:=j+1;
         if (c[j+1]>=men) and (j<(pol+1)) then begin
                                        men:=c[j+1];
                                        c[j+1]:=c[pol+1];
                                        c[pol+1]:=men;
                                                           end
                                                           else begin
                                   if (c[j]>=c[j+1]) and (j<>n) then begin
                                           men:=c[j];
                                           c[j]:=c[j+1];
                                           c[j+1]:=men;
                                                                                end;
                                                                 end;
                   until j=n;
for j:=1 to n do write(C[j],' ');
writeln('ENTER - Выход');

     (* Получаем 1 2 3 4 5 6 7 8 9 *)
 
readln;
END.
============================================
Могу только еще раз напомнить:
Возможно, есть еще и другие варианты решения.
LEND
В мире временном, сущность которого - тлен,
Не сдавайся вещам несущественным в плен. © О.Х.