1. 程式人生 > >詳細剖析:楊氏矩陣Young Taleau資料結構

詳細剖析:楊氏矩陣Young Taleau資料結構

楊氏矩陣YOUNG Tableau,作為一個既類似於二叉排序樹(BST),又類似於堆結構的一種簡單資料結構。乍看一下,其實就是一個二維陣列,但是該資料結構有著明顯的特點,即陣列的每一行元素嚴格單調遞增(當然也可以遞減),同時每一列的元素也是嚴格單調遞增(同前面)。有了這種特點,使得它對於查詢某些元素,比堆的效能要好;而對於插入或者刪除元素,比BST更方便。        楊氏矩陣資料結構的特點有(如圖1):

1.是一個M*N矩陣,並且對於同一行左邊的元素要小於(或大於)右邊的元素,同一列上面的元素要小於(或大於)下面的元素;

2.如過元素不夠組成一個M*N矩陣,即矩陣有一定的空餘空間,那麼可以採用+∞(遞減的情況為-∞)填充。

圖1 楊氏矩陣 1 6 7 10 3 8 11 14 12 15 16 + ∞ 13 18 +∞ + ∞       楊氏矩陣常用的操作:       1.對有空餘控制元件的矩陣插入元素k,記為INSERT(Y,k);

2.矩陣刪除位置為(m,n)處的元素,記為DELETE(Y,(m,n));

3.從矩陣中查詢元素k,記為FIND(Y,k);

4.對楊氏矩陣所有元素進行排序輸出;

5.其他相關的操作,類似於返回最大值MAX(Y),或者MIN(Y),以及除去最大最小值EXTRACT_MAX(Y),EXTRACT_MIN(Y)等等。

下面對這些操作進行詳細分析:

1.矩陣插入元素k,首先將元素k置於矩陣的空餘位置上。注意放置位置為先最左邊的最上面(或者是最上面的最左邊),因此可以將元素k放置在第四行第二列的位置上(或者是第三行第三列),假設k為2,那麼圖1變為:

圖2 楊氏矩陣 1 6 7 10 3 8 11 14 12 15 16 + ∞ 13 18 2 + ∞

2作為新插入的元素,可以看到它打破了楊氏矩陣的特性,需要進行處理,保持楊氏矩陣的特點。從圖中看到2所在列的上面一個元素為A[3][2]=15,所在行的前面元素為A[4][1]=20,並且A[4][1]>A[3][2]>2,所以2最好跟元素A[4][1]進行位置交換,如果跟所在列的位置A[3][2]進行交換的話,因為A[4][1]>A[3][2],列雖然保持了遞增的特點,但是又破壞了行遞增的特點,即還需要交換A[4][1]和A[3][2]的位置,所以應該讓2與本行的元素A[4][1]進行交換;反之,如果該行的前一個元素要小於該列的上一個元素那麼新插入的元素應該與該列的元素前一個交換位置。這裡我們可以總結出插入元素步驟:

插入元素的初始位置為A[m][n],

如果A[m-1][n]>=A[m][n-1],並且A[m-1][n]>A[m][n],將A[m-1][n]與A[m][n]進行交換,對A[m-1][n]進行插入操作; 如果A[m-1][n]<=A[m][n-1],並且A[m][n-1]>A[m][n],將A[m][n-1]與A[m][n]進行交換,對A[m][n-1]進行插入操作; 如果A[m][n-1]<A[m][n]並且A[m-1][n]<A[m][n],此時A[m][n]位置正確,插入完成。       根據上面的操作具體的步驟:

圖3 因為18>16,所以2和18交換位置 1 6 7 10 3 8 11 14 12 15 16 + ∞ 13 2 18 + ∞ 圖4 因為15>13,所以2和15交換位置 1 6 7 10 3 8 11 14 12 2 16 + ∞ 13 15 18 + ∞ 圖5 因為12>8,所以2和12交換位置 1 6 7 10 3 8 11 14 2 12 16 + ∞ 13 15 18 + ∞ 圖6 因為3已經到了最左邊,所以2與上面的元素對比,3>2,交換位置,此時交換結束 1 6 7 10 2 8 11 14 3 12 16 + ∞ 13 15 18 + ∞        小結:根據上面的操作可以看出,存在一個遞迴過程,即不斷將插入元素網上或者往左移動,時間複雜度最差為o(M+N)。        2.  對於矩陣刪除位置為(m,n)處的元素,可以借鑑上面的插入操作,但是比較的方法簽好與上面相反。刪除元素是跟該元素下面的元素以及後面的元素進行比較,如果後面的元素小於下面的元素,那麼後面的元素與該元素交換,反之依然。具體的操作如下。

刪除元素的初始位置為A[m][n],

如果A[m+1][n]<A[m][n+1]],將A[m+1][n]與A[m][n]進行交換,對A[m+1][n]進行刪除操作; 如果A[m+1][n]>A[m][n+1],將A[m][n+1]與A[m][n]進行交換,對A[m][n+1]進行插入操作; 如果A[m][n+1]、A[m+1][n]元素存在,並且都為+∞,此時A[m][n]位置調整結束,將A[m][n]=+∞,刪除完成。        例如刪除(2,2)的元素8,如圖7:

圖7 楊氏矩陣刪除元素(2,2) 1 6 7 10 3 8 11 14 12 15 16 + ∞ 13 18 +∞

  • ∞       現在要刪除元素8的位置為A[2][3],可以看到其下面和後面的元素分別為15和11,而15>11,所以應該用11與8交換: 圖8 8和15交換位置 1 6 7 10 3 11 8 14 12 15 16 + ∞ 13 18 +∞
  • ∞         現在要刪除元素8的位置為A[2][4],可以看到其下面和後面的元素分別為16和14,而16>14,所以應該用14與8交換: 圖9 8和14交換 1 6 7 10 3 11 14 8 12 15 16 + ∞ 13 18 +∞
  • ∞ 8和14交換完後,可以看到8的下面為+∞,而後面沒有元素,因此8交換結束,把8置為+∞即可。       小結:根據上面的操作可以看出,存在一個遞迴過程,即不斷將刪除元素往下或者往後移動,時間複雜度最差為o(M+N)。

3.  對於矩陣查詢元素k,由於楊氏矩陣並不是完全排序的,而只是區域性排好順序,即對每一行、每一列單獨來說是排好順序的,而對於不同的行,誰大誰小誰也摸不準。因此不能直接使用2叉排序樹的查詢演算法,而需要對2叉排序樹的查詢演算法進行修改。具體的操作如下。

檢視矩陣的左下角,如果左下角元素比k大,那麼就可以跳過左下角元素所在的行,往上繼續查詢;而如果左下角元素比k小,就可以跳過左下角元素所在列,往後面繼續查詢;(或者檢視矩陣的右上角,如果右上角元素比k大,那麼就可以跳過右上角元素所在的列,往前繼續查詢;而如果右上角元素比k小,就可以跳過右上角元素所在行,往下面繼續查詢;或者兩種步驟間歇性進行) 如果根據上面的兩步,以及搜尋完這個矩陣,還是沒有找到元素k,則返回布林值false,如果找到k值對應的元素,則返回true,並且儲存其對應的座標。        例如搜尋的元素8,如圖10:

圖10 楊氏矩陣刪除元素(2,2) 1 6 7 10 3 8 11 14 12 15 16 + ∞ 13 18 +∞

  • ∞          現在要搜尋元素8,首先查詢最左下角的元素13,13>8,所以可以拋棄13對應的行,如圖11: 圖11 刪除13對應的行 1 6 7 10 3 8 11 14 12 15 16 + ∞        繼續搜尋元素8,可以繼續檢視左下角元素為12,12>8,可以拋棄12對應的行,如圖12: 圖12 刪除12對應的行 1 6 7 10 3 8 11 14         繼續搜尋元素8,可以繼續檢視左下角元素為3,3<8,可以拋棄3對應的列,如圖13: 圖12 刪除3對應的列 6 7 10 8 11 14         繼續搜尋元素8,繼續檢視左下角元素為8,搜尋完畢,返回對應的座標值。        小結:根據上面的操作可以看出,存在一個迴圈(遞迴)過程,即不斷往上或者往前移動,時間複雜度最差為o(M+N)。

4.對楊氏矩陣所有元素進行排序輸出,可以借鑑刪除元素操作來完成排序。我們根據楊氏矩陣元素的特徵可以看出:A[1][1]是矩陣中值最小的。所以依次刪除A[1][1],並輸出A[1][1],直到矩陣都為+∞,排序輸出結束。

5.返回最大值MAX(Y),或者MIN(Y),以及除去最大最小值EXTRACT_MAX(Y),EXTRACT_MIN(Y)這些操作都是前面三種基本操作的不同形式或者不同的組合,這裡不再贅述了。