順時針,逆時針,zigzag矩陣詳解

來源:互聯網
上載者:User

        最近對矩陣的研究比較多一點,一來,因為加的幾個QQ群裡一直有人在討論這個問題,而且討論者甚眾,看來大家對這個問題還是挺有興趣的;二來,去年自己去有道的一次面試中就遇到了這樣一個問題,很遺憾的是當時並沒有答出來,於是與有道失之交臂,感到挺遺憾的。但這還不是全部,因為一年前我曾做過這樣一道題,而且還考慮了很久,是一個公司的面試題,到真正需要用的時候反而寫不出來了,足見自己學習的不連貫,孔夫子幾千年前就說的道溫故而知新,自己到現在都不會用。面試回去花了很長時間終於找到了自己曾做過的這個題,令我不能淡定的是,那個程式在一個叫做“有道筆試”的檔案夾下,真的有瞬間石化的感覺,真是應了一句當今的網路熱門語“出來混遲早是要還的”,於是痛定思痛,要把這個矩陣問題好好搞明白。

       首先是,順時針矩陣。

      1        2        3      4      5

     16     17     18    19      6

     15     24     25     20     7

     14     23     22     21     8

     13     12     11     10     9

        通過我們的觀察,可以知道該矩陣首先沿著最大圈逆時針逐漸增大,當圍成一個圈後然後再進入第二個圈同樣做逆時針遞增。規律找到了,如何輸出這樣一個矩陣呢?當然就要我們找到語言的規律。首先我先用一種比較簡單,比較好理解的方法來做。首先我們定義四個變數,top,bottom,left,right,分別來對應矩陣的上、下、左、右四個方向。在矩陣的最上面一行,我們發現橫座標始終不變,改變的只是縱座標,而矩陣的最右列,改變的也只是橫座標,而縱座標不發生改變,剩下的依次類推,這樣我們就能得到下面的代碼。

void clockwise()
{
        int top = -1, bottom = N, left = -1, right = N;
        int i, j;
        int n = 1;
        i = top + 1, j = left + 1;
        while(top <= bottom && left <= right)
        {
                top++; bottom--; left++; right--;
                while(j <= right)
                {
                        A[i][j] = n++;
                        j++;
                }
                j--; i++;
                while(i <= bottom)
                {
                        A[i][j] = n++;
                        i++;
                }
                i--; j--;
                while(j >= left)
                {
                        A[i][j] = n++;
                        j--;
                }
                j++; i--;
                while(i > top)
                {
                        A[i][j] = n++;
                        i--;
                }
                i++; j++;
        }
  }

        這種方法思路比較簡單,容易理解,因為不涉及到比較複雜的歸納推理。下面的方法則比較晦澀,這個方法是建立在對這個圖有深入理解的基礎上的,剛開始可能會覺得不好理解,但是多看幾遍應該就能明白其中的奧妙。

void clockwise(int A[][N])
{
    int i, j, k = 1;
    for(i = 0; i < N/2; i++)
    {
        for(j = i; j < N - i - 1; j++)
            A[i][j] = k++;
        for(j = i; j < N - i - 1; j++)
            A[j][N - i - 1] = k++;
        for(j = N - i - 1; j > i; j--)
            A[N-i-1][j] = k++;
        for(j = N - i - 1; j > i; j--)
            A[j][i] = k++;
    }
    if(N%2 == 1)
        A[N/2][N/2] = k;
       }
}

          在順時針方向的遞增明白之後,逆時針方向的矩陣程式便能很好地寫出了,這裡不再寫出,留給讀者自己編程練習。

         下面我著重介紹zigzag矩陣的產生,zigzag矩陣,就是我們俗稱的“之字形”矩陣。熟悉影像處理的同學們應該對zigzag數組很熟悉了,在JPEG圖形演算法中首先對映像進行分塊處理,一般分成互不重疊且大小一致的塊,量化的結果保留了低頻部分的係數,去掉了高頻部分的係數。量化後的係數按zigzag掃描重新組織,然後進行哈夫曼編碼。

1      2      6      7      15

3      5      8     14     16

4      9     13    17     22

10   12   18     21    23

11   19    20    24    25

          仔細分析上面的矩陣,首先從左上方出發,向右遞增一位,然後沿著右上到左下的對角線遞增,但遇到邊界遍向下走,然後再沿著從左下到右上的方向繼續遞增。映像很好理解。

void zigzag(int A[][N])

{

         int i, j, min = 1, max = N * N;

         for(i = 0; i < N / 2; i++)

         {

                  if(i%2 == 0)

                  {

                         for(j = i; j >= 0; j--)

                         {

                                   A[j][i] = min++;

                                   A[N-1-j][N-1-i+j]=max--;

                         }

                 }

                 if(i%2 != 0)

                 {

                            for(j = 0; i < =i; i++)

                            {

                                      A[j][i-j] = min++;

                                      A[N-1-j][N-1-i+j]=max--;

                            }

                  }

         }

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.