Strona główna » Algorytmy » Artykuły » Macierze cz. 1
1011
 

Macierze cz. 1

· część 1 · część 2 · część 3 · Wyznacznik ·

Macierze

Macierze najczęściej zapisuje się w postaci prostokątnej tablicy. Możliwe jest również zapisanie ich w postaci wektora długość równej ilości wierszy macierzy pomnożonej przez ilość kolumn macierzy. Najbardziej popularną metodą jest przechowywanie macierzy w tablicach podwójnie indeksowanych czyli prościej mówiąc dwuwymiarowych. Jednak prócz samej tabeli musimy przechowywać wielkość tabeli: ilość wierszy i kolumn. W celu uproszczenia zapisu użyjemy struktury.

Implementacja

Struktura

(2.) Nowo utworzona klasa macierz będzie przechowywać informację w tablicy dwuwymiarowej dane. Dodatkowo będzie możliwy dostęp do (4. - 6.) ilości jej kolumn oraz (8. - 10.) wierszy poprzez pobranie długości odpowiedniego wymiaru.

C++
C#
  1. class Macierz {
  2.   protected double[,] dane;
  3.   int Wierszy {
  4.     get { return dane.GetLength(0); }
  5.   }
  6.   int Kolumn {
  7.     get { return dane.GetLength(1); }
  8.   }

(2.) Przy tworzeniu uzyskujemy wskaźnik na macierz, więc aby zmodyfikować pola danych nowo utworzonej macierzy to będziemy używać "->" zamiast "."(, którą używamy dla typ, a nie typ*). (3. - 4.) Następnie przypisujemy wielkość naszej zmiennej macierzy. (5.) Zmienna table to nasza 2D tablica, którą na sam koniec przekażemy do matrix. (7.) Następnie dla każdego wiersza tworzymy listę double i (9.) każdy element ustawiamy na 0. Na koniec iteracji (11.) przekazujemy wskaźnik do zmiennej table i (12.) zwracamy macierz.

Domyślny konstruktor macierzy pobiera wartości n i m oznaczających kolejno ilość wierszy i kolumn. Zadaniem konstruktora jest inicjalizacja tablicy do przechowywania danych.

C++
C#
  1. public Macierz(int n, int m) {
  2.   dane = new double[n, m];
  3. }

Bardzo często przy macierzach omawia się macierze kwadratowe, dlatego warto uwzględnić szybki i prosty sposób na tworzenie macierzy kwadratowych.

C++
C#
  1. public Macierz(int n) : this(n, n) { }

Na podstawie napisanej klasy Macierz można już napisać klase dziedziczącą po niej MacierzJednostkowa. Macierz jednostkowa na swojej głównej diagonali ma same jedynki. Prościej mówiąc każda liczba o współrzędnych x i y, gdzie x = y ma wartość 1.

C++
C#
  1. class MacierzJednostkowa : Macierz {
  2.   public MacierzJednostkowa(int n) : base(n) {
  3.     for (int i = 0; i < n; i++)
  4.       dane[i, i] = 1;
  5.   }
  6. }

Modyfikowanie macierzy

Załóżmy, że chcemy napisać funkcję, która usunie i-ty wiersz macierzy. Oznacza to, że musimy utworzyć nową tablicę wielkości n - 1 × m. Następnie przepisać każdy wiersz po kolei pomijając wiersz, który chcemy usunąć.

C++
C#
  1. public void usuńWiersz(int v) {
  2.   double[,] temp = new double[Wierszy - 1, Kolumn];
  3.   for (int i = 0, x = 0; i < Wierszy; i++) {
  4.     if (i != v - 1) {
  5.       for (int y = 0; y < Kolumn; y++) {
  6.         temp[x, y] = dane[i, y];
  7.       }
  8.       x++;
  9.     }
  10.   }
  11.   dane = temp;
  12. }

(2.) Tworzymy tymczasową, mniejszą tablicę dwuwymiarową i (3. - 10.) przepisujemy wszystkiw wiersze prócz wskazanego. Należy tutaj mieć dwie oddzielne zmienne. Jedna z nich pozwala i pozwala na przechodzenie po kolejnych wierszach, a x przechowuje pod którym indeksem wiersza zapisujemy dane w tablicy tymczasowej.

Usuwanie kolumny macierzy jest trochę bardziej skomplikowane, ale opiera się na identycznym schemacie:

C++
C#
  1. public void usuńKolumne(int v) {
  2.   double[,] temp = new double[Wierszy, Kolumn - 1];
  3.   for (int x = 0; x < Wierszy; x++) {
  4.     for (int j = 0, y = 0; j < Kolumn; j++) {
  5.       if (j != v - 1) {
  6.         temp[x, y] = dane[x, j];
  7.         y++;
  8.       }
  9.     }
  10.   }
  11.   dane = temp;
  12. }

Mnożenie macierzy

Mnożenie macierzy przez skalar oznacza pomnożenie każdej liczby w macierzy przez skalar:

C++
C#
  1. public static Macierz operator *(Macierz m, double a) {
  2.   Macierz w = new Macierz(m.Wierszy, m.Kolumn);
  3.   for (int x = 0; x < m.Wierszy; x++) {
  4.     for (int y = 0; y < m.Kolumn; y++) {
  5.       w.dane[x, y] = a * m.dane[x, y];
  6.     }
  7.   }
  8.   return w;
  9. }

Wypisywanie macierzy

Struktura Matrix jest naszym wytworem i standardowe biblioteki nie potrafią wypisać jej na konsole. Jednak możemy napisać specjalną funkcje, która nam to umożliwi:

C++
C#
  1. public override string ToString() {
  2.   string s = "";
  3.   for (int x = 0; x < Wierszy; x++) {
  4.     for (int y = 0; y < Kolumn; y++) {
  5.       s += String.Format("{0}\t", dane[x, y]);
  6.     }
  7.     s += '\n';
  8.   }
  9.   return s;
  10. }

Funkcja używa tu specjalnego znaku "\t", który wypisuje tabulator, aby macierz była wyrównana w kolumnach.

Testowanie funkcji

Poniższy fragment kodu prezentuje użycie niektórych napisanych funkcji:

C++
C#
  1. static void Main(string[] args) {
  2.   Macierz matrix = new MacierzJednostkowa(4);
  3.   Console.WriteLine("Nowa macierz:\n{0}", matrix);
  4.   Console.WriteLine("\n\nUsuwamy drugi wiersz macierzy:");
  5.   matrix.usuńWiersz(2);
  6.   Console.WriteLine(matrix);
  7.   Console.WriteLine("\n\nUsuwamy drugą kolumnę macierzy:");
  8.   matrix.usuńKolumne(2);
  9.   Console.WriteLine(matrix);
  10.   Console.WriteLine("\n\nMnożymy macierz przez skalar 3:");
  11.   matrix = matrix * 3.0;
  12.   Console.WriteLine(matrix);
  13.   Console.ReadKey();
  14. }

Zadania

Zadanie 1

Napisz funkcję sumujWszystko(), która zsumuje wszystkie liczby w macierzy i zwróci wynik jako liczbę rzeczywistą.

Zadanie 2

Napisz funkcję lub konstruktor, który pozwoli użytkownikowi wprowadzić macierz czyli: