Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Алгоритмы обхода матрицы

Ответить
Настройки темы
Алгоритмы обхода матрицы

Ветеран


Сообщения: 1404
Благодарности: 135

Профиль | Отправить PM | Цитировать


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

Например, если дана матрица A(m,n) {a(i,j)-элементы} и m=n=3, то проход a(1,1) -> a(1,2) ->a(1,3) -> a(2,3) -> a(3,3) -> a(3,2) -> a(3,1) -> a(2,1) --> a(2,2)

Насколько эффективен будет следующий алгоритм обхода: сначала делаем поворот (с располаганием элементов) на 3 четверти, затем циклично до конца повороты на 2 четверти. Какие более эффективные алгоритмы можно использовать?
Код: Выделить весь код
'Расположить элементы матрицы по часовой стрелке в возрастающем порядке
Dim a(),x(), sx,posy,posx,numx,numy,k,i,j,l,m,n,s, u, msg, msgst,msgp, nn,tmp

input()
msg=sort(x)
sx=split(msg,"~")
msgp=arr_to_string(sx,1)
msgst=arr_to_string(a,2)

u=0
l=0
numy=Ubound(a,1)
numx=Ubound(a,2)
posy=0
posx=0
i=0

''''''''''один поворот на 3 четверти'''''''''''''
For j=posx To numx
		a(i,j)=eval(sx(l)) 		
		l=l+1			
Next
j=j-1
numx=posx
posx=j

For i=posy+1 To numy
	a(i,j)=eval(sx(l))	
	l=l+1		
Next
i=i-1
numy=posy
posy=i

if m<>0 then
For j=posx-1 To numx Step -1	
	a(i,j)=eval(sx(l))
	l=l+1		
Next
j=j+1 
numx=posx
posx=j
numy=numy+1
end if



'''''''''''следующие повороты на 2 четверти''''''''''
nn=1
while (l<Ubound(sx))
	if ((nn Mod 2) <> 0) then

		if nn>2 then numy=numy+1
		
		For i=posy-1 To numy Step -1	
			a(i,j)=eval(sx(l))			
			l=l+1			
		Next
		i=i+1
		numy=posy
		posy=i
		
		For j=posx+1 To numx-1
				a(i,j)=eval(sx(l)) 				
				l=l+1			
		Next 
		j=j-1
		numx=posx
		posx=j

		nn=nn+1
		
	else
			
		For i=posy+1 To numy-1	
			a(i,j)=eval(sx(l))	
			l=l+1			
		Next
		i=i-1
		numy=posy
		posy=i
		
		if nn>1 then numx=numx+1
		
		For j=posx-1 To numx  Step -1
				a(i,j)=eval(sx(l)) 
				l=l+1			
		Next 
		j=j+1
		numx=posx
		posx=j
		
		nn=nn+1
		
	end if
wend


''''''''' Вывод матрицы '''''''''
msg = arr_to_string (a,2)
msgBox("Последовательность: "&vbcrlf& msgp&vbcrlf& _
	"Начальная матрица: "&vbcrlf& msgst&vbcrlf&_
	"Конечная матрица: "&vbcrlf& msg&vbcrlf)

''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function sort (x())
	Dim i,j,s

	For i=0 To Ubound(x)-1
		For j=i+1 To Ubound(x)
			If (x(i)>x(j)) then 
				tmp=x(j)
				x(j)=x(i)
				x(i)=tmp
			end if			
		next
	next

	s=join(x,"~")
	sort=s
End Function

Sub input()
	Dim k,i,j,t
	k=0
	m=inputbox("Размерность по y?")
	while (not isnumeric(m) or isempty(m) or isnull(m) or m<0)
			m=inputbox("Введено некорректное значение. Введите размерность по y")
	wend
	n=inputbox("Размерность по x?")
	while (not isnumeric(n) or isempty(n) or isnull(n) or n<0)
			n=inputbox("Введено некорректное значение. Введите размерность по x")
	wend
	Redim a(m,n)
	For i=0 To Ubound(a,1)
		For j=0 To Ubound(a,2)
			t=inputbox("Введите a("&i&","&j&")")
			while (not isnumeric(t) or isempty(t) or isnull(t))
			t=inputbox("Введено некорректное значение. Введите a("&i&","&j&")")
			wend
			
			Redim Preserve x(k)			
			a(i,j)=t	
			x(k)=eval(a(i,j))			
			k=k+1
		Next
	Next
	
End Sub

Sub arr_print(p(), r)
	Dim i,j
	Select Case r
		Case "1"
			For i=0 To Ubound(p)
					msgBox "p("&i&")/"&p(i)&"/"&vbcrlf
			Next
		Case "2"
			For i=0 To Ubound(p,1)
				For j=0 To Ubound(p,2)		
					msgBox "p("&i&","&j&")="&p(i,j)&vbcrlf
				Next
			Next
		case else
			MsgBox("Not supported")					
	End Select
End Sub


Function arr_to_string(p(), r)
	Dim msg,i,j
	msg=""
	Select Case r
		Case "1"
			For i=0 To Ubound(p)
					msg=msg & p(i) & " "					
			Next
			msg=msg&vbcrlf
		Case "2"
			For i=0 To Ubound(p,1)
				For j=0 To Ubound(p,2)
					msg=msg & p(i,j) & " "					
				Next
				msg=msg&vbcrlf
			Next
		case else
			MsgBox("Not supported")	
	End Select						
arr_to_string=msg
End Function
Главное, чтобы мне подобные задачи на экзамене или на зачете не попались, потому что за 2-3 часа написать нереально.

Отправлено: 09:04, 25-10-2006

 

Googler


Сообщения: 3665
Благодарности: 1563

Профиль | Отправить PM | Цитировать


1. Хорошо бы иметь таблицу преобразования (ТП) между координатами элемента в матрице и положением в одномерном массиве "раскрученной спирали", тогда заполнение выполняется за один проход... К примеру для матрицы 3x3 таблица преобразования будет (x,y) = {(1,2) (1,3) (2,3) (3,3) (3,2) (3,1) (2,1) (2,2)}, т.е. по сути это двумерный массив указателей.

2. Теперь как можно построить ТП. Допустим, мы можем построить ее для одного оборота обхода матрицы (MxN) начав с левого верхнего угла, т.е. имеем ф-цию Fun (N, M, I, J), добавляющую в конец глобальной ТП координаты обхода (I, J - "координаты" начала обхода). Так вот, полный путь состоит из последовательности: Fun (N,M, 0,0) --> Fun (N-2,M-2, 1,1) --> Fun (N-4,M-4, 2,2) ... пока размерность массива >0.

3. Алгоритм Fun (M, N, I, J) линеен и состоит из четырех отрезков:
- y=J, x увеличивается от I до I+N-1
- x=I+N-1, y увеличивается от J до J+M-1
- y=J+M-1, x уменьшается от x=I+N-1 до I
- x=I, y уменьшается от J+M-1 до J+1

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

Отправлено: 12:50, 25-10-2006 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Сообщения: 1404
Благодарности: 135

Профиль | Отправить PM | Цитировать


Цитата:
З.Ы. Это только общий алгоритм... Звиняюсь, но из вашего кода я мало чего понял, и про "четверти" с "поворотами" тоже.
Полный поворот для матрицы 3x3 это проход от a(1,1) до a(2,1) - по 2 строкам и 2 столбцам
Три четверти поворота это проход от a(1,1) до a(3,1) - по 2 строкам и столбцу

В коде делается следующее.
Задаются начальные значения позиции в матрице и конечные значения:
1. проход по первой строке (четверть от полного поворота по часовой стрелке от a(1,1) до a(1,1)). После каждой четверти поворота меняем начальные значения на конечные. Строка(y) фиксируется, столбцы(x) меняются.
2. проход по последнему столбцу (вторая четверть поворота). Столбец(x) фиксируется, строки(y) меняются.
3. проход по последней строке (четверть поворота - всего 3/4 поворота)

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

По-моему вы предложили то же самое..
Есть ли еще какие-нибудь способы?

-------
Ehhh.. what's up, doc?..


Отправлено: 16:09, 25-10-2006 | #3

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


есть, их полно. Правда чем дальме - тем более извращённый способ получается.
Например, сведём всё к одной операции прохода строчки и одной операции поворота матрицы (всё это в цикле).

в цикле:
1. прошли верхнюю строчку
2. повернули на 90 CCW (кто фотошоп видел, поймёт)

дальше варианты: копировать матрицу или поворачивать координатную ось. Дешевле повернуть ось (понятней - наоборот). Так и сделаем!
Код: Выделить весь код
// извиняюсь, что пишу не на языке вопроса, но если идея зацепит, попробую перевести
class pass_matrix
{
    static const int gwidth = 10;  // начальная ширина
    static const int gheight = 20; // начальная высота

    int matrix[gwidth*gheight];

    int width;  // ширина
    int height; // высота
    int a, b, c, d; // преобразование координат
        // x1 = a*x + b
        // y1 = c*y + d
    int x, y;  // смещение

    void print()
    {
        std::cout << "{" << x << ", " << y << "}: "
                << matrix[x + y*qwidth] << "\n";
    }

public:
    pass_matrix() :
        matrix(),
        width(gwidth),
        height(gheight),
        a(1), b(0),
        c(1), d(0),
        x(0), y(0)
    {
        // начальная позиция:
        //  0123
        // 0x->.
        // 1....
        // 2....
    }
private:

    void step()
    {
        // делаем один шаг
        x += a;
        y += b;
    }

    void rotate()
    {
        // шаг назад
        //  0123
        // 0....x
        // 1...|
        // 2...v
        x += c - a;
        y += d - b;

        // поворот матрицы (направления)
        int a1 = c;
        int b1 =  d;
        int c1 = -a;
        int d1 =  -b;

        a = a1;
        b = b1;
        c = c1;
        d = d1;

        // поворот и усечение размеров
        --height;
        std::swap(width,height);
    }

public:
    void main()
    {
        while (0<height)
        {
            for (int w=width; 0<=--w; step())
            {
                print();
            }

            rotate();
        }
    }
};
если в линейных преобразованиях не напутал, то должно работать

Последний раз редактировалось pva, 25-10-2006 в 22:25.

Это сообщение посчитали полезным следующие участники:

Отправлено: 22:07, 25-10-2006 | #4



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Алгоритмы обхода матрицы

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
C/C++ - [решено] Нахождение обратной матрицы методом Гаусса и рассширенной матрицы D.Y. Программирование и базы данных 64 06-05-2011 22:59
Доступ - [решено] Способы обхода закрытого реестра Игорь Анатольевич Microsoft Windows 2000/XP 21 12-12-2008 02:10
Java - Капча и способы её обхода. vaniak Программирование и базы данных 2 26-05-2008 17:47
Программные средства обхода firewall mzu Сетевые технологии 5 07-05-2004 23:37
алгоритмы поиска. Vlad Drakula Программирование и базы данных 9 16-01-2004 09:09




 
Переход