Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Транспонирование матрицы, хранящейся в одномерном массиве 
V
    Опции темы
Alagert
Дата 8.1.2006, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Есть прямоугольная матрица, нужно ее траспонировать на месте.
Матрица записана построчно в одномерный массив. Для траспонирования нужно использовать этот же массив и можно еще некоторое количество переменных, число которых не зависит от размерности матрицы. Со слов моего препода, понял, что их должно быть 1 или 2.

Погите плиз разобраться с этой задачей, очень нужно!
Всем спасибо!
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
maxim1000
Дата 8.1.2006, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



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

пример:
матрица 2х3 (в одномерном представлении): 1, 2, 3; 4, 5, 6
1-й шаг: смотрим на первый элемент - это (1,1) его не надо менять (так всегда будет на первом шаге)
2-й шаг: смотрим на второй элемент - это (1,2): там стоит 2, а должно быть 4, меняем их местами
и так далее

на самом деле, если подумать, то алгоритм поиска можно будет заменить на просто вычисление какого-нибудь аналитического выражения, но думать лень smile


--------------------
qqq
PM WWW   Вверх
Illuminaty
Дата 8.1.2006, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



а - массив [0..n], где n = m*m - 1, где m - размерность матрицы
temp - переменная
транспонирование:
Код
for (i = 0; i < n; i ++) {
  for (j = 0; j < i - 1; j++) {
    temp = a[i*n + j];
    a[i*n + j] = a[j*n + i];
    a[j*n + i] = temp;
  }
}


Это сообщение отредактировал(а) Illuminaty - 8.1.2006, 15:26
PM MAIL ICQ   Вверх
Alagert
Дата 8.1.2006, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(Illuminaty @ 8.1.2006, 15:25)
а - массив [0..n], где n = m*m - 1, где m - размерность матрицы
temp - переменная
транспонирование:
Код
for (i = 0; i < n; i ++) {
  for (j = 0; j < i - 1; j++) {
    temp = a[i*n + j];
    a[i*n + j] = a[j*n + i];
    a[j*n + i] = temp;
  }
}

Твой вариант проходит для квадратных матриц. С ним все ясно.
А как быть с прямоугольной матрицей?
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Illuminaty
Дата 8.1.2006, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Alagert, двойку тебе по алгебре в зачетку поставить надо smile
Прямоугольные матрицы не транспонируются
PM MAIL ICQ   Вверх
Alagert
Дата 8.1.2006, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(Illuminaty @ 8.1.2006, 16:53)
Alagert, двойку тебе по алгебре в зачетку поставить надо smile
Прямоугольные матрицы не транспонируются

У меня 5 по матану за все курсы smile
Прямоугольная матрица замечательно траспонируется! Была матрица MxN, а стала NxM.
Прямоугольные матрицы не обращаются(если не рассматривать случай псевдообратных матриц)


--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Illuminaty
Дата 8.1.2006, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Цитата(Alagert @ 8.1.2006, 18:00 Найти цитируемый пост)

У меня 5 по матану за все курсы
Тогда и флаг тебе в руки smile
PM MAIL ICQ   Вверх
Illuminaty
Дата 8.1.2006, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Признаю ошибку. Мои 5 по алгебре остались в прошлом веке. Действительно, перепутал с обратными... Позор на мою седую голову... Ладно хоть преподаватель не видит по алгебре - его бы удар хватил smile
В связи с этим помогу с алгоритмом, но через некоторое время...
PM MAIL ICQ   Вверх
Alagert
Дата 8.1.2006, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(Illuminaty @ 8.1.2006, 17:54)
Признаю ошибку. Мои 5 по алгебре остались в прошлом веке. Действительно, перепутал с обратными... Позор на мою седую голову... Ладно хоть преподаватель не видит по алгебре - его бы удар хватил smile
В связи с этим помогу с алгоритмом, но через некоторое время...

Всем свойственно ошибаться. Огромное спасибо за обещание помочь.
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Mal Hack
Дата 8.1.2006, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



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

Код
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
 mm : array[1..10] of array[1..10] of integer;
 c,n,m,i,j:integer;
 per : boolean = false;
begin
 n := 4;
 m := 1;

 for i := 1 to n do
  begin
   for j := 1 to m do
    begin
     mm[i,j] := random(10);
     write( mm[i,j]: 4 );
    end;
   writeln;
  end;

 writeln;

 if n > m then
  begin
   c := n;
   n := m;
   m := c;
   per := true;
  end;

 for i := 1 to n do
  for j := i + 1 to m do
   begin
    c := mm[i,j];
    mm[i,j] := mm[j,i];
    mm[j,i] := c;
   end;

 if per = true then
  begin
   c := n;
   n := m;
   m := c; 
  end;

 for i := 1 to m do
  begin
   for j := 1 to n do
    write( mm[i,j]: 4 );

   writeln;
  end;


 readln; 
end.

PM ICQ   Вверх
Illuminaty
Дата 8.1.2006, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Mal Hack, прочитай условие внимательно
Цитата(Alagert @ 8.1.2006, 15:30 Найти цитируемый пост)

Матрица записана построчно в одномерный массив.


PM MAIL ICQ   Вверх
Mal Hack
Дата 8.1.2006, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



Illuminaty массив массива строк. Или имеется ввиду вектор?
PM ICQ   Вверх
Alagert
Дата 8.1.2006, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(Mal Hack @ 8.1.2006, 20:42)
Illuminaty массив массива строк. Или имеется ввиду вектор?

Для простоты есть интовый массив размерности m*n, туда построчно записана вся матрица.
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
maxim1000
Дата 8.1.2006, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



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


--------------------
qqq
PM WWW   Вверх
Mal Hack
Дата 8.1.2006, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



Работает когда m > n, щас думаю над обратным случаем...
Код
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
 mm : array[1..50] of integer;
 c,n,m,i,j:integer;
begin
 n := 3;
 m := 3;
 
 for i := 1 to n do
  begin
   for j := 1 to m do
    begin
     mm[(i-1)*m+j] := random(10);
     write( mm[(i-1)*m+j]: 4 );
    end;
   writeln;
  end;

 writeln;

 for i := 1 to n do
  for j := i + 1 to m do
   begin
    c := mm[(i-1)*m+j];
    mm[(i-1)*m+j] := mm[i+(j-1)*m];
    mm[i+(j-1)*m] := c;
   end;

 for i := 1 to m do
  begin
   for j := 1 to n do
    write( mm[(i-1)*m+j]: 4 );

   writeln;
  end;


 readln; 
end.



Это сообщение отредактировал(а) Mal Hack - 8.1.2006, 21:52
PM ICQ   Вверх
Mal Hack
Дата 8.1.2006, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



Alagert уточни в каком именно виде и как хранится матрица, и в каком ее надо записать.
PM ICQ   Вверх
Alagert
Дата 8.1.2006, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Матрица записана след образом:
Код

int * matrix =new int[m*n];

//for example
for(int=0;i<m*n;i++) matrix[i]=i;



т.е была матрица: 1 2 3
4 5 6

записана в массив будет в виде : 1 2 3 4 5 6
после траспонирования: 1 4
2 5
3 6
в массиве будет: 1 4 2 5 3 6

Пасибо за вариант, ща буду его разбирать.

Это сообщение отредактировал(а) Alagert - 8.1.2006, 22:55
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Akina
Дата 8.1.2006, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Алгоритм:
Исходная матрица - A (M,N) в векторе V (M*N)
Конечная матрица - B (N,M)
Возьмем элемент вектора V(K).
В исходной матрице его адрес:
A (K mod N, K div N)
В конечной матрице его адрес должен стать:
B (K div N, K mod N)
Т.е. в векторе V его адрес станет
V( N*(K mod N) + (K div N))

Итого:

Код

For K = 0 to M*N
   If K > (N*(K mod N)+(K\N)) Then
      ' Менять местами надо только один раз
      ' Диагональные - вообще не надо
      SWAP V(K), V(N*(K mod N)+(K\N))
   End if
Next


PS. Писано на коленке, проверьте.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Alagert
Дата 8.1.2006, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(Akina @ 8.1.2006, 23:20)
Алгоритм:
Исходная матрица - A (M,N) в векторе V (M*N)
Конечная матрица - B (N,M)
Возьмем элемент вектора V(K).
В исходной матрице его адрес:
A (K mod N, K div N)
В конечной матрице его адрес должен стать:
B (K div N, K mod N)
Т.е. в векторе V его адрес станет
V( N*(K mod N) + (K div N))

Итого:

Код

For K = 0 to M*N
   If K > (N*(K mod N)+(K\N)) Then
      ' Менять местами надо только один раз
      ' Диагональные - вообще не надо
      SWAP V(K), V(N*(K mod N)+(K\N))
   End if
Next


PS. Писано на коленке, проверьте.

Работает, если исправить кое что:
1) возьмем V(K), в исходной матр это будет A(K/N, k mod N)
2) в траспонированной B(K mod N, K/N)
3) перестановка в векторе V(M*(K mod N) + K/N)

Вот вроде так. В твоем варианте получается, что траспонирование матр никак не зависит от ее второй размерности.

2 Mal Hack
В коде, который ты привел ошибка: ты выходишь за границы массива, когда меняешь элементы. И ты принял, что матр квадратная.

Ща еще потестирую.
ВСЕМ БОЛЬШОЕ СПАСИБО!
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Illuminaty
Дата 9.1.2006, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



На тот случай если алгоритм Akina не сработал привожу полную рабочую программу.
Код
program MatrixTransp;
{$APPTYPE CONSOLE}
uses
  SysUtils;

var
  N: Integer; // по вертикали
  M: Integer; // по горизонтали
  a: array of Integer; // наш массив
  maxmodul: Integer; // максимальный модуль для пометки элемента массива
  temp_a, temp_i, i, j: Integer; // временные переменные

procedure InitArray;
var
  i, j: Integer; // счетчик
begin
{инициируем размерность матрицы и заполняем случайными числами от -50 до 50}
  Write('Введите N ');
  Read(N);
  Write('Введите M ');
  Read(M);
  SetLength(a, M*N);
  Randomize;
  for i := 0 to M*N - 1 do
    a[i] := Random(100) - 50;
{Выведем матрицу}
  for i:= 0 to N-1 do
  begin
    for j:= 0 to M-1 do
      Write(a[i*M + j]: 4);
    writeLn;
  end;
end;

procedure FindMaxModule;
{находим максимальное по модулю число и записываем его модуль в maxmodule}
var
  i: Integer; // счетчик
begin
  maxmodul := a[0];
  for i := 0 to M*N - 1 do
    if maxmodul < abs(a[i]) then
      maxmodul :=  abs(a[i]);
end;

procedure Mark(i: Integer);
{"помечаем" элемент массива, путем увеличения его по модулю на maxmodul + 1}
begin
  if a[i] >= 0 then
    a[i] := a[i] + maxmodul + 1
  else
    a[i] := a[i] - maxmodul - 1;
end;

procedure Remark(i: Integer);
{"размечаем" элемент массива, путем уменьшения его по модулю на maxmodul + 1}
begin
  if a[i] >= 0 then
    a[i] := a[i] - maxmodul - 1
  else
    a[i] := a[i] + maxmodul + 1;
end;

function isMark(i: Integer): Boolean;
{возвращает true, если элемент "помечен" и false в противном случае}
begin
  Result := abs(a[i]) > maxmodul;
end;

function TransPos(i: Integer): Integer;
{получение номера в массиве, по которому лежит транспонированный эллемент}
begin
  Result := (i mod n) * m + (i div n);
end;

begin
  InitArray;
  FindMaxModule;

  for i := 0 to N*M - 1 do
  begin
    if not isMark(i) then // если с элементом раньше не работали
    begin
      temp_i := i;
      while not isMark(TransPos(temp_i)) do begin
        {обмен значениями}
        temp_a := a[TransPos(temp_i)];
        a[TransPos(temp_i)] := a[temp_i];
        a[temp_i] := temp_a;
        {помечаем элемент}
        Mark(temp_i);
        temp_i := TransPos(temp_i);
      end;
    end;
  end;

  {размечаем все меченные элементы}
  for i := 0 to N*M - 1 do
  begin
    if isMark(i) then
      Remark(i);
  end;


// выведем транспонированную матрицу
  writeLn;
  for i:= 0 to M-1 do
  begin
    for j:= 0 to N-1 do
      Write(a[i*N + j]: 4);
    writeLn;
  end;

  readln;
  readln;
end.

PM MAIL ICQ   Вверх
maxim1000
Дата 9.1.2006, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата

В исходной матрице его адрес:
A (K mod N, K div N)
В конечной матрице его адрес должен стать:
B (K div N, K mod N)
Т.е. в векторе V его адрес станет
V( N*(K mod N) + (K div N))

проблема в том, что тот элемент, на место которого нужно поставить K-й, необязательно должен стать на его место...
пример:
исходная матрица - 2 строки, 3 столбца
0 1 2 3 4 5
переходит в
0 3 1 4 2 5

например, 1 становится на место 2, но не наоборот...

P.S. если не ошибся... smile


--------------------
qqq
PM WWW   Вверх
Illuminaty
Дата 9.1.2006, 02:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Почему не будет работать алгоритм Akina.
Потому что при транспонировании прямоугольной матрицы элементы не будут заменятся двунаправленно. Т.е. пусть у нас есть матрица:
┌─┬─┬─┐
│0│1│2│
├─┼─┼─┤
│3│4│5│
└─┴─┴─┘, она транспонируется в матрицу
┌─┬─┐
│0│3│
├─┼─┤
│1│4│
├─┼─┤
│2│5│
└─┴─┘, если все записать в строку, то получим, что была строка [0, 1, 2, 3, 4, 5], получили транспонированием строку [0, 3, 1, 4, 2, 5]. Т.е. преобразовния следующие
0 -> 0;
1 -> 2 -> 4 -> 3 -> 1;
5 -> 5;
В зависимости от размерности матрицы может быть разное количество таких цепочек.
при реализации этих преобразований нужно запомнить, с какими элементами производили преобразования, а с какими - нет. Для этого в моем решении вводится переменная maxmodul, которая хранит максимальный модуль из входной матрицы. Элемент, с которым происвели преобразование, помечаем путем увеличения его модуля на maxmodul + 1. В конце работы, для всех помеченных элементов модуль уменьшаем на maxmodul + 1.
Добавлено @ 02:08
maxim1000 немного раньше это написал. Да еще и с тем же примером, что и у меня
PM MAIL ICQ   Вверх
maxim1000
Дата 9.1.2006, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата

Для этого в моем решении вводится переменная maxmodul, которая хранит максимальный модуль из входной матрицы. Элемент, с которым происвели преобразование, помечаем путем увеличения его модуля на maxmodul + 1.

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


--------------------
qqq
PM WWW   Вверх
Illuminaty
Дата 9.1.2006, 02:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



maxim1000, можно и тип Real (или double) сделать. Я просто думал над пометкой без использования дополнительных массивов. Насчет переполнения я тоже думал, но ничего другого не придумал. Времени на это не было. И так программу накидал - должен был, а то лопухнулся с определениями. Ладно хоть Alagert не расскажет моему преподавателю по алгебре как лопухнулся.smile Во всяком случае, программа работаетsmile Если кто придумает как лучше помечать элементы - милости прошу. Только функции изменить и вперед!
PM MAIL ICQ   Вверх
maxim1000
Дата 9.1.2006, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата

Если кто придумает как лучше помечать элементы - милости прошу

помечать элементы никак нельзя - нельзя заставить матрицу хранить больше информации, чем то, насколько она расчитана
в случае с double произойдет потеря точности...
так что получится ненастоящее транспонирование...
Добавлено @ 02:45
вот пришел в голову еще один способ:
(для начала сразу скажу - первый индекс - строка или количество строк, второй - столбец или количество столбцов)
наша задача - транспонировать матрицу m*n
мы точно знаем, какие элементы будут в конце массива - нужно просто взять последний столбец и вытащить его элементы в конец
дальше можно отбросить последние m элементы и обработать (n-1)*m матрицу, которая задана в оставшейся части массива...


--------------------
qqq
PM WWW   Вверх
Illuminaty
Дата 9.1.2006, 02:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



Цитата(maxim1000 @ 9.1.2006, 03:40 Найти цитируемый пост)
помечать элементы никак нельзя
но у меня же получился один вариантsmile
Можно, кстати, перевести в строковый тип и помечать добавлением какого-нибудь символа (или группы символов)
Добавлено @ 02:50
Цитата(maxim1000 @ 9.1.2006, 03:40 Найти цитируемый пост)

вот пришел в голову еще один способ:
, а те элементы, что в конце, ты куда денешь?smile
У этого способа та же проблема...

PM MAIL ICQ   Вверх
maxim1000
Дата 9.1.2006, 02:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Код

void Transpose(int *Array,unsigned int RowCount,unsigned int ColumnCount)
{
  while(ColumnCount>1)
  {
    //draw last column into the tail of the array
    //(begin from the bottom)
    for(unsigned int c=0;c<RowCount;c++)
    {//draw (ColumnCount-1,RowCount-1-c)-th element to the end
      unsigned int index=ColumnCount-1+ColumnCount*(RowCount-1-c);
      unsigned int target=ColumnCount*RowCount-1-c;
      int temp=Array[index];
      for(i=index;i<target;++i)
        Array[i]=Array[i+1];
      Array[target]=temp;
    }
    //proceed with smaller matrix
    --ColumnCount;
  }
}

вот...
правда, тоже писалось на коленках smile
Добавлено @ 03:02
Цитата(Illuminaty @ 9.1.2006, 02:47 Найти цитируемый пост)

но у меня же получился один вариант

который решает задачу только для некоторых матриц (у которых не слишком большие элементы)
Цитата(Illuminaty @ 9.1.2006, 02:47 Найти цитируемый пост)

Можно, кстати, перевести в строковый тип и помечать добавлением какого-нибудь символа (или группы символов)

нельзя, т.к.это потребует дополнительных расходов памяти, пропорциональных размерностям матрицы
Цитата(Illuminaty @ 9.1.2006, 02:47 Найти цитируемый пост)

а те элементы, что в конце, ты куда денешь?

они сдвинутся
под "вытаскиванием" элементов я имел в виду такую операцию - берем элемент, все, которые после него, сдвигаем в сторону начала массива (занимая освободившееся место), а взятый элемент - в конец массива (ну или на каком-то расстоянии от конца)
Добавлено @ 03:08
пример с матрицей 2*3
1 2 3 4 5 6
1. вытаскиваем элементы последнего столбца (3 и 6) в конец массива (начиная с нижних)
1.1. вытаскиваем 6 - его вытаскивать не надо, так тут ничего и делать не надо
1.2. вытаскиваем 3:
3 запоминаем (одна временная переменная)
1 2 3 4 5 6 -> 1 2 4 5 (неважно что) 6 -> 1 2 4 5 3 6
Добавлено @ 03:11
а теперь сводим задачу (2*3) к задаче (2*2), уменьшая количество столбцов и размер массива (точнее, размер той части массива, с котороймы работаем), т.е. транспонируем матрицу 2*2: 1 2 4 5
по тому же алгоритму


--------------------
qqq
PM WWW   Вверх
Mayk
Дата 9.1.2006, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 2
Всего: 134



А если менять цепочкой, а не линейно?

То есть берем i-ый элемент и ставим его на корректное место j.
После этого мы берем не (i+1) элемент(как не единожды предлагалось ранее), а элемент j (то есть тот, на котором должен стоять i).
Если же такого уже нет, то берем i+1.
При этом i+1 считается обработанным, если в обходе его цепочки мы натолкнемся на обработанный элемент.

Цепочка - это...

Пример:

Есть
123
456

(123456)

Хотим

14
25
36

(142536)


Отображение A->At такое:
1->1, 2->3, 3->5, 4->2, 5->4, 6->6

Цепочка - это вот такая ерунда: 1->1, 2->3->5->4->2 ну и прочее. Блин. Не могу сформулировать, но интуитивно надеюсь понятно.


Запускаем алгоритм:
1) Берем i=1. (123456 <- текущий массив)
2) 1->1. Единица уже была(только что), не меняем (123456)
3) Берем 2. Ставим её на 3. 3 запоминаем (122456)
4) Ставим 3 на 5. 5 запомиаем (122436)
5) Ставим 5 на 4. 4 запоминаем(122536)
6) Ставим 4 на 2. мы начинали с двойки, поэтому останавливаемсч(142536)

7) Берем 3. Мы её не будем трогать, так как цепочка 3->5->4->2 приводит к уже обработанной 2.(142536)
8) Берем 4. Не меняем, так как 4->2 приводит к обработанной 2(142536)
9) Берем 5. Не меняем, так как 5->4 приводит к обработанной 4(142536)
10) Берем 6. Не меняем, так как 6->6 приводит к обработываемой 6(142536)

Готово. 142536

Попробую обосновать инвариантом цикла,

Инвариант цикла -
цепочки всех элементов до текущего оттранспорированны.

Инициализация - текущего элемента нет.
Предшественников нет. (ну или даже 1-ый элемент всегда оттранспорирован)
Сохранения инварианта - мы меняем местами только те элементы, цепочки которых не содержат
предшествующих элементов. Иными словами если что-то было верно, то оно останется верным.
Если что-то было неверным, оно станет верным. Мы трогаем лишь элементы цепочки.
Завершение - Все цепочки оттранспорированны. => оттранспорированны ВСЕ элементы матрицы .

ЗЫ. Цепочка образует цикл, это всё очень имхо и это я не доказывал, но имхо это так. Все таки A=Att.
Добавлено @ 09:34
Тьфу блин, как же я это такой пост пропустил.
Идея с цепочками уже была у Illuminaty
Ну ладно. По крайне мере можете попниать обоснование.

Это сообщение отредактировал(а) Mayk - 9.1.2006, 09:38


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Illuminaty
Дата 9.1.2006, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



maxim1000, круто! Проверил - действительно работает.
Только твоя функция немного неправильно работает, но это из-за
Цитата(maxim1000 @ 9.1.2006, 03:58 Найти цитируемый пост)
тоже писалось на коленках
.
Вот полностью работающая программа
Код
program MatrixTransp;
{$APPTYPE CONSOLE}
uses
  SysUtils;

var
  N: Integer; // по вертикали
  M: Integer; // по горизонтали
  a: array of Integer; // наш массив
  maxmodul: Integer; // максимальный модуль для пометки элемента массива
  i, j: Integer; // временные переменные

procedure InitArray;
var
  i, j: Integer; // счетчик
begin
{инициируем размерность матрицы и заполняем случайными числами от -50 до 50}
  Write('Введите N ');
  Read(N);
  Write('Введите M ');
  Read(M);
  SetLength(a, M*N);
  Randomize;
  for i := 0 to M*N - 1 do
    a[i] := Random(100) - 50;
{Выведем матрицу}
  for i:= 0 to N-1 do
  begin
    for j:= 0 to M-1 do
      Write(a[i*M + j]: 4);
    writeLn;
  end;
end;

procedure Transpose;
var
  i, j, temp, c, k: Integer;
begin
  k := 0;
  for j := M -1 downto 0 do
    for i := N -1 downto 0 do
    begin
      temp := a[i*(j+1) + j];
      for c := i*(j+1) + j to M*N - k - 2 do
        a[c] := a[c+1];
      a[M*N - k - 1] := temp;
      k := k + 1;
    end;
end;


begin
  InitArray;
  Transpose;
// выведем транспонированную матрицу
  writeLn;
  for i:= 0 to M-1 do
  begin
    for j:= 0 to N-1 do
      Write(a[i*N + j]: 4);
    writeLn;
  end;

  readln;
  readln;
end.
Проверено - работает
PM MAIL ICQ   Вверх
Alagert
Дата 9.1.2006, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Всем огромное спасибо! А я вот вчера в 1.30 уже сломался. Проверил вариант Akina и бухнулся спать.
Сейчас буду разбирать все ваши идеи.
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Alagert
Дата 9.1.2006, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Всем огромное спасибо!
2 maxim1000 Спасибо за алг! Все работает. Сам думал сводить задачу к меньшей размерности, но до твоего варианта так и не додумался!

12 числа покажу преподу, реакцию отпишу. Может есть еще легче вариант!
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
maxim1000
Дата 9.1.2006, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(Mayk @ 9.1.2006, 09:29 Найти цитируемый пост)

Тьфу блин, как же я это такой пост пропустил.
Идея с цепочками уже была у Illuminaty
Ну ладно. По крайне мере можете попниать обоснование.

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


--------------------
qqq
PM WWW   Вверх
Alagert
Дата 12.1.2006, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Я показал преподу это решение! Он был удивлен, что все это так просто работает! Говорит, что я чего мухлюю! Я рассказал про вариант с цепочками, он сказал, что это гиблое дело. И из этого нормальный алгоритм не выйдет!

ЗЫ Может подскажете как автаматически оттестировать этот алг?
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
Illuminaty
Дата 12.1.2006, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


/*Антон Захаров*/
***


Профиль
Группа: Комодератор
Сообщений: 1238
Регистрация: 19.3.2005
Где: Россия, Казань

Репутация: 1
Всего: 56



возьми мой код
откомпилируй его при преподе
запусти и пусть он введет свои данные

А на самом деле составь хорошо оформленное математическое доказательство, но это уже в другой раздел..
PM MAIL ICQ   Вверх
myxacuk
Дата 16.4.2016, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 16.4.2016

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0888 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.