Wypisywanie całej macierzy symetrycznej z jej połówki (macierzy trójkątnej dolnej)

0

Problem jest raczej prosty - mimo tego nie potrafię sobie z nim dać rady...

Mam macierz trójkątną dolną, np.
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15

W ten sposób - dla oszczędności miejsca - zapisuję macierz symetryczną...
Chciałbym teraz wypisać jej wszystkie elementy. Czyli chcę uzyskać coś takiego jako wynik (pełną macierz symetryczną):
1 2 4 7 11
2 3 5 8 12
4 5 6 9 13
7 8 9 10 14
11 12 13 14 15

To, co najistotniejsze - macierz przechowuję w tablicy jednowymiarowej!

Wypisywanie po wierszu nie jest problemem - schody zaczynają się w drugiej pętli, gdzie przechodzę po kolumnach - nie wiem jak obliczyć współrzędną elementu w tablicy :)

	int matrix[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
	int num=0, rozm=5;

	for(int i=0; i<rozm; i++)
	{
		num+=i;
		for(int j=0; j<i+1; j++)
		{
			cout << matrix[num+j] << " ";
		}
		for(int j=i+1; j<rozm; j++)
		{
			cout << matrix[???] << " ";
		}
		cout << endl;
	}

Za każdą pomoc będę wdzięczny

0

Udało mi się wykombinować takie rozwiązanie:

	int matrix[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
	int num=0, num2=0, num3=0, rozm=6;

	for(int i=0; i<rozm; i++)
	{
		num+=i;
		for(int j=0; j<i+1; j++)
		{
			cout << matrix[num+j] << " ";
		}
		num2=num+i;
		num3=i;
		for(int j=i+1; j<rozm; j++)
		{
			num3++;
			num2+=num3;
			cout << matrix[num2] << " ";
		}
		
		cout << endl;
	}
 

To teraz trochę inaczej zadam pytanie - czy jest mi ktoś w stanie pomóc napisać funkcję, która będzie mapować (przeliczać) współrzędne z zapisu macierzy trójkątnej, dolnej (czyli nawet nie całej symetrycznej) w tablicy dwuwymiarowej na zapis w tablicy jednowymiarowej (czyli zwracać odpowiednią współrzędną na tab. jednowymiarowej)?
Czyli: int coordinates(int row, int col, int size);

5

Wykorzystam zstępujący sposób projektowania algorytmów, rekurencję i matematykę na poziomie podstawówki, a więc do dzieła!

Główny kod (dla wygody indeksuję macierz od 1 zarówno dla wierszy jak i dla kolumn):

for i=1 to rozmiar:
   for j=1 to rozmiar:
      wypisz(i, j)
   nl()  // drukuje nową linię

Funkcja wypisz(i, j) będzie nam wypisywać liczbę (element) w i-tym wierszu i w j-tej kolumnie. Macierz jest symetryczna - stąd element o indeksach np. (2,3) jest taki sam jak (3,2). Zastanówmy się, jak to wykorzystać? Otóż wypisujmy te elementy w identyczny sposób, tak jakby macierz miała tylko właśnie indeksy które tworzą macierz trójkątną dolną. Kiedy indeksy nie będą pasować do tej macierzy? Wtedy kiedy numer kolumny jest większy od numeru wiersza. Rozwiązanie: prosta zamiana współrzędnych i z j.

wypisz(i,j):
   if j>i:
      wypisz(j,i)
   else:
      (... tutaj coś będzie ...)

Teraz zredukowaliśmy problem do wypisywania elementów macierzy trójkątnej. Wykorzystujemy sumę ciągu arytmetycznego i piszemy prostą funkcję. Liczba elementów w n pierwszych wierszach macierzy trójkątnej to n(n+1)/2. Piszemy sobie funkcję:

suma(n):
   return n*(n+1)/2

Pozostało ustalenie pozycji w wektorze z danymi, jest to oczywiste. Uzupełniamy naszą funkcję wypisz i kończymy zadanie:

wypisz(i,j):
   if j>i:
      wypisz(j,i)
   else:
      print vector[suma(i-1)+j]+" "

Założyłem również, że vector jest indeksowany od 1 :)

@n0name_l, nie rozumiem bulwersacji, tytuł tego działu to Algorytmu i struktury danych, a nie który język programowania jest najpiękniejszy. Poza tym jaki jest problem odjąć 1 od całości? W reprezetacji algorytmu zaciemniłoby to tylko ideę. Dziękuję.
edit 2: Prosiłbym jeszcze o rozwinięcie myśli - co jest w tym haniebnego?

0

Dziękuję bardzo za pomoc.
Tylko jeszcze jedno pytanie - w którym miejscu muszę odjąć jedynkę, jeśli numeruję od zera?

int matrix[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
int rozm=6;

int suma(int n){
	return n*(n+1)/2;
}
void wypisz(int i, int j)
{
	if(j>i)
		wypisz(j,i);
	else
	{
		cout << matrix[suma(i-1)+j] << " ";
	}
}
int main(){
	

	for(int i=0; i<rozm; i++)
	{
		for(int j=0; j<rozm; j++)
		{
			wypisz(i, j);
		}
		cout << endl;
	}
	system("Pause");

}

Bo jeśli zapiszę matrix[suma(i-1)+j-1], to nie działa poprawnie.
I jeszcze odwołując się do mojego drugiego posta, gdzie zaproponowałem funkcję, która będzie przeliczać współrzędne z tablicy dwuwymiarowej na jednowymiarową - czy da się to zrobić prościej (mniej obciążająco dla procesora) niż to rozwiązanie:

int coordinates(int row, int col){
	int coord=0;
	for(int i=0; i<=row; i++)
	{
		coord+=i;
	}
	coord+=col;
	return coord;
}

Już wszystko jasne - dsokal, jesteś genialny ;) Dzięki wielkie!
funkcja konwertująca współrzędne to będzie:

int coordinates(int row, int col){
	return row*(row+1)/2 + col;
}
0

Oczywiście kluczowe było też aby te dwa fory zaczynały lecieć od 1. Ale rozumiem, że rozwiązałeś swój problem, więc nie ma co go drążyć :)

0

Witam mam ten sam problem czy ktoś to co jest tu zapisane w C++ zapisać w pełnym przykładzie w delphi dla macierzy np 5x5 z buttonem dla Stringgrida

0

Macierz trójkątna to szczególny przypadek, macierzy pasmowej o której j był wątek.
https://4programmers.net/Forum/C_i_C++/360870-mnozenie_macierzy_pasmowej_przez_wektor
pod którym dałem taki kod.

0

Dziękuję za info ale nie jestem wstanie przekonwertować go na delphi, czy jesteś w stanie taki krótki program na bazie Stringgrida zrobić pod delphi

1 użytkowników online, w tym zalogowanych: 0, gości: 1