3. C#

3.9. Transpozice

Pokud je matice symetrická , označujeme úhlopříčnou spojnici protilehlých míst (počátečního prvku a posledního prvku matice) jako hlavní diagonálu. Pro prvky na hlavní diagonále platí, že jejich index řádku i je roven indexu sloupce , tj.  Pro případ matice o rozměru např. 3 x 3 jsou prvky umístěné na hlavní diagonále označeny zeleně - viz Obrázek 1. 

Prvky na hlavní diagonále ve dvourozměrném poli

Obrázek 1: Prvky na hlavní diagonále ve dvourozměrném poli

Transpozice prvků podle hlavní diagonály znamená prohození osově souměrných prvků, kde osu otáčení představuje hlavní diagonála - viz Obrázek 2. 

Transpozice prvků podle hlavní diagonály ve dvourozměrném poli

Obrázek 2: Transpozice prvků podle hlavní diagonály ve dvourozměrném poli

Abychom prohodili jednotlivé prvky podle hlavní diagonály, stačí nám pouze procházet jednotlivé prvky v oranžové oblasti, které jsou umístěny nad hlavní diagonálou (pokud bychom také procházeli i prvky pod hlavní diagonálou, znovu bychom prohazovali nazpátek již jednou prohozené prvky a matice by zůstala nezměněna) - viz Obrázek 3. Prvky na hlavní diagonále není zapotřebí prohazovat.

Průchod prvky nad hlavní diagonálou ve dvourozměrném poli při transpozici prvků podle hlavní diagonály

Obrázek 3: Průchod prvky nad hlavní diagonálou ve dvourozměrném poli při transpozici prvků podle hlavní diagonály

V následující metodě bez výstupu s názvem HlavniTranspozice, která je také umístěna v regionu Operace s polem, je zachycena podstata transpozice prvků podle hlavní diagonály. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici, jejíž prvky chceme transponovat podle hlavní diagonály. Dále metoda obsahuje tři proměnné:

  • pom - pomocná proměnná pro přesun osově souměrných prvků matice podle hlavní diagonály
  • i - index řádku matice aktuálně procházeného prvku (deklarace přímo v cyklu)
  • j - index sloupce matice aktuálně procházeného prvku (deklarace přímo v cyklu)

První rozhodovací příkaz zajišťuje, že pokud počet řádků není roven počtu sloupců (nejedná se o symetrickou matici), je metoda ukončena včetně výpisu varovného hlášení. Pokud je matice symetrická, využijeme pro procházení jednotlivých prvků nad hlavní diagonálou dva cykly s krokem. První vnější cyklus bude probíhat od prvního do předposledního řádku matice. Jedná se totiž o oranžovou oblast prvků nad hlavní diagonálou. Pro procházení sloupců v jednotlivých řádcích matice slouží další vnitřní cyklus s krokem. Jak si můžeme všimnout, je zapotřebí procházet pouze ty prvky, jejichž index sloupce je o 1 vyšší, než index řádku aktuálně procházeného prvku (do průchodu chceme zahrnout pouze oranžovou oblast). V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oranžové oblasti do pomocné proměnné. Tento princip jsme již využili dříve, např. při vzestupném řazení prvků v řádcích pomocí metody Bubble Sort. Prvek v oranžové oblasti je přepsán osově souměrným prvkem podle hlavní diagonály umístěným pod hlavní diagonálou pomocí příkazu pole[i, j] = pole[j, i];. Do osově souměrného prvku pod hlavní diagonálou je následně uložena hodnota z pomocné proměnné.

/// <summary>
/// Transpozice prvků matice podle hlavní diagonály
/// </summary>
/// <param name="m"> počet řádků matice </param>
/// <param name="n"> počet sloupců matice </param>
/// <param name="pole"> matice, kde jsou prvky otočeny podle hlavní diagonály </param>
static void HlavniTranspozice(int m, int n, int[,] pole)
{
    /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle 
     * hlavní diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */
    int pom;
 
    // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak...
    if (m != n)
    {
        // Výpis varovného upozornění
        Console.WriteLine("Nelze transponovat obdélníkovou matici");
        // Ukončení metody
        return;
    }
    // Jinak ...
    else
    {
        // Od počátečního až předposledního řádku matice
        for (int i = 0; i < m - 1; i++)
        {
            // Od i + 1-tého sloupce do posledního sloupce matice
            for (int j = i + 1; j < m; j++)
            {
                // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné
                pom = pole[i, j];
               
                /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem
                 * podle hlavní diagonály, tj. na pozici [j,i] */
                pole[i, j] = pole[j, i];
               
                /* Přepsání osově souměrného prvku na pozici [j,i] prvkem uloženým
                 * v pomocné proměnné */
                pole[j, i] = pom;
            }
        }
    }
}

 Kód 1: Deklarace statické metody bez návratu s názvem HlavniTranspozice

Pokud je matice symetrická  označujeme protilehlou úhlopříčnou spojnici protilehlých míst (posledního prvku prvního řádku a prvního prvku posledního řádku) jako vedlejší diagonálu. Pro prvky na vedlejší diagonále platí, že jejich index řádku i je roven indexu sloupce pokud .  Pro případ matice o rozměru 3 x 3 jsou prvky umístěné na vedlejší diagonále označeny modře - viz Obrázek 4. 

Prvky na vedlejší diagonále ve dvourozměrném poli

Obrázek 4: Prvky na vedlejší diagonále ve dvourozměrném poli

Transpozice prvků podle vedlejší diagonály znamená prohození osově souměrných prvků, kde osu otáčení představuje vedlejší diagonála - viz Obrázek 5. 

Transpozice prvků podle vedlejší diagonály ve dvourozměrném poli

Obrázek 2: Transpozice prvků podle vedlejší diagonály ve dvourozměrném poli

V následující metodě bez výstupu s názvem VedlejšíTranspozice je zachycena podstata transpozice prvků podle vedlejší diagonály - viz Kód 2. Metoda přijímá tři parametry: počet řádku, počet sloupců matice a matici, jejíž prvky chceme transponovat. Dále metoda obsahuje tři proměnné:

  • pom - pomocná proměnná pro přesun osově souměrných prvků matice podle vedlejší diagonály
  • i - index řádku matice aktuálně procházeného prvku  (deklarace přímo v cyklu)
  • j - index sloupce matice aktuálně procházeného prvku (deklarace přímo v cyklu)

První rozhodovací příkaz zajišťuje, že pokud počet řádků není roven počtu sloupců (nejedná se o symetrickou matici), je metoda ukončena včetně výpisu varovného hlášení. Pokud je matice symetrická, využijeme pro procházení jednotlivých prvků nad vedlejší diagonálou dva cykly s krokem. První vnější cyklus bude probíhat od prvního do předposledního řádku matice. Jedná se totiž o oranžovou oblast prvků nad vedlejší diagonálou. Pro procházení sloupců v jednotlivých řádcích matice slouží další vnitřní cyklus s krokem. Jak si můžeme všimnout, je zapotřebí procházet pouze ty prvky, jejichž index sloupce je menší než rozdíl počtu řádků a indexu řádku aktuálně procházeného prvku (do průchodu chceme zahrnout pouze oranžovou oblast). Matice je symetrická m = n, takže nezáleží zda menšenec představuje počet řádků, nebo počet sloupců. V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oranžové oblasti do pomocné proměnné. Prvek v oranžové oblasti na pozici [i, j] je přepsán osově souměrným prvkem podle vedlejší diagonály umístěným pod vedlejší diagonálou na pozici [m - j - 1, m - i - 1]. Do osově souměrného prvku pod vedlejší diagonálou je následně uložena hodnota z pomocné proměnné.

/// <summary>
/// Transpozice prvků matice podle vedlejší diagonály
/// </summary>
/// <param name="m"> počet řádků matice </param>
/// <param name="n"> počet sloupců matice </param>
/// <param name="pole"> matice, kde jsou prvky otočeny podle vedlejší diagonály </param>
static void VedlejsiTranspozice(int m, int n, int[,] pole)
{
    /* Deklarace: 'pom' ... pomocná proměnná pro přesun osově souměrných prvků matice podle 
     * vedlejší diagonály; 'i' ... index řádku matice; 'j' ... index sloupce matice */
    int pom;
 
    // Pokud počet řádek není roven počtu sloupců (matice není symetrická), pak...
    if (m != n)
    {
        // Výpis varovného upozornění
        Console.WriteLine("Nelze transponovat obdélníkovou matici");
        // Ukončení metody
        return;
    }
    // Jinak ...
    else
    {
        // Od počátečního až předposledního řádku matice
        for (int i = 0; i < m - 1; i++)
        {
            // Od i + 1-tého sloupce do posledního sloupce matice
            for (int j = 0; j < m - i; j++)
            {
                // Uložení aktuálního prvku matice na pozici [i,j] do pomocné proměnné
                pom = pole[i, j];
 
                /* Přepsání aktuálního prvku matice na pozici [i,j] osově souměrným prvkem
                 * podle vedlejší diagonály, tj. na pozici [m-j-1,m-i-1] */
                pole[i, j] = pole[m - j - 1, m - i - 1];
 
                /* Přepsání osově souměrného prvku na pozici [m-j-1, m-i-1] prvkem uloženým
                 * v pomocné proměnné */
                pole[m - j - 1, m - i - 1] = pom;
            }
        }
    }
}

Kód 2: Deklarace statické metody bez návratu s názvem VedlejsiTranspozice