4. C#

4.8. Transpozice

Pro transpozici prvků matice podle hlavní diagonály je v regionu Operace s polem, která je součástí regionu Pomocné metody, volána soukromá metoda bez návratu s názvem HlavniTranspozice. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici. Metoda obsahuje tři lokální proměnné. Proměnná pom reprezentuje pomocnou proměnnou pro přesun osově souměrných prvků matice podle hlavní diagonály. Ostatní dvě lokální proměnné i - index řádku matice aktuálně procházeného prvku a j - index sloupce matice aktuálně procházeného prvku jsou deklarovány 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í v dialogovém oknu. 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 oblast prvků umístěných 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 oblast nad hlavní diagonálou). V těle cyklu provádíme vzájemné prohození prvků pomocí uložení hodnoty prvků z oblasti nad diagonálou 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 oblasti nad diagonálou 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é.

Následující zdrojový kód obsahuje deklaraci metody HlavniTranspozice- viz Kód 1.

/// <summary>
/// Metoda pro transpozici 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 </param>
private 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í
        MessageBox.Show("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 metody pro transpozici prvků podle hlavní diagonály (HlavniTranspozice)

Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnTranspoziceHlavni_Click - viz Kód 2. V rámci těla metody budeme volat předchozí deklarovanou metodu HlavniTranspozice, které předáme tři parametry - počet řádků matice, počet sloupců matice a matici (uložené v datových složkách třídy). Vzhledem k tomu, že v metodě bude upravena matice, je vhodné tuto změněnou matici uživateli zobrazit. Proto matici zobrazíme jak do objektu typu TextBox, tak i do objektu typu ListView umístěných na formuláři. 

/// <summary>
/// Volání metody pro transpozici prvků matice podle hlavní diagonály
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnTranspoziceHlavni_Click(object sender, RoutedEventArgs e)
{            
    // Zavolání metody pro transpozici prvků matice podle hlavní diagonály
    this.HlavniTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole);
    // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři
    this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole);
    // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři
    this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole);
}

Kód 2: Deklarace metody pro zavolání metody pro transpozici prvků matice podle hlavní diagonály - výpis na formuláři (BtnTranspoziceHlavni_Click)

Pro transpozici prvků matice podle hlavní diagonály je v regionu Operace s polem, která je součástí regionu Pomocné metody, volána soukromá metoda bez návratu s názvem VedlejsiTranspozice - viz Kód 3. Metoda přijímá tři parametry: počet řádků, počet sloupců matice a matici. Metoda obsahuje tři lokální proměnné. Proměnná pom reprezentuje pomocnou proměnnou pro přesun osově souměrných prvků matice podle hlavní diagonály. Ostatní dvě lokální proměnné i - index řádku matice aktuálně procházeného prvku a j - index sloupce matice aktuálně procházeného prvku jsou deklarovány přímo v cyklu. 

Stejně jako v předchozím případu transpozice podle hlavní diagonály, první rozhodovací příkaz metody zajišťuje, že pokud počet řádků není roven počtu sloupců, je metoda ukončena včetně výpisu varovného hlášení v dialogovém oknu. 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 o 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 oblast nad vedlejší diagonálou). 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 oblasti nad vedlejší diagonálou do pomocné proměnné. Prvek v oblasti nad diagonálou 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>
/// Metoda pro transpozici 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 </param>
private 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á) ...
    if (m != n)
    {
        // Výpis varovného upozornění
        MessageBox.Show("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 3: Deklarace metody pro transpozici prvků podle vedlejší diagonály (VedlejsiTranspozice)

Přemístíme se zpět do regionu Události a jeho části Operace s polem. V tomto regionu upravíme metodu obsluhy události stisknutí tlačítka BtnTranspoziceVedlejsi_Click - viz Kód 4. V rámci těla metody budeme volat předchozí deklarovanou metodu VedlejsiTranspozice, které předáme tři parametry - počet řádků matice, počet sloupců matice a matici (uložené v datových složkách třídy). Vzhledem k tomu, že v metodě bude upravena matice, je vhodné tuto změněnou matici uživateli zobrazit. Proto matici zobrazíme jak do objektu typu TextBox, tak i do objektu typu ListView umístěných na formuláři. 

/// <summary>
/// Volání metody pro transpozici prvků matice podle vedlejší diagonály
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnTranspoziceVedlejsi_Click(object sender, RoutedEventArgs e)
{
    // Zavolání metody pro transpozici prvků matice podle vedlejsi diagonály
    this.VedlejsiTranspozice(this.pocetRadku, this.pocetSloupcu, this.pole);
    // Zavolání metody pro zobrazení matice do objektu (TextBox) na formuláři
    this.ZobrazitPoleJakoText(this.pocetRadku, this.pocetSloupcu, this.pole);
    // Zavolání metody pro zobrazení matice v objektu (ListView) na formuláři
    this.ZobrazitPoleVListView(this.pocetRadku, this.pocetSloupcu, this.pole);
}

Kód 4: Deklarace metody pro zavolání metody pro transpozici prvků matice podle vedlejší diagonály - výpis na formuláři (BtnTranspoziceVedlejsi_Click)