杨氏矩阵的一些性质

在笔试题目中看到一个关于杨氏矩阵(Young Tableau)的问题,说实话,杨氏矩阵我还是第一次听说,就在网上百度谷歌了一番,感觉这个数据结构还蛮有意思的。而且这个数据结构在做增、删、查找的复杂度都比较低。以前只知道学书本上面的问题,现在才知道不能光学课本,还要了解那些能够在实际中有用的东西。

首先介绍一下这个数据结构的定义,杨氏矩阵就是有一个m*n的矩阵,让后有一数组 a[k], 其中 k<=m*n ,然后把a[k]中的数填入 m*n 的矩阵中,填充规则为:

  1. 每一行每一列都严格单调递增(有其他的版本是递减,其原理相同);
  2. 如果将a[k]中的数填完后,矩阵中仍有空间,则填入 ∞。

1

2

3

4

5

6

 

1

3

5

7

8

11

a

2

6

9

14

15

19

b

4

10

21

23

33

57

c

34

37

45

55

56

d

e

现在讨论一下插入操作、删除操作和查找操作的详细过程:

插入操作:

本操作的时间复杂度为O( n + m ),其操作类似于堆排序算法。它的堆的结构在这里表现为某个元素Y[x, y] 下面和右面的两个元素 Y[x, y+1] ,Y[x+1, y]均比Y[x, y]要大。于是其插入算法可以描述为,首先把待插入元素以行为主序置于所有有效数字(除了无穷以外的数)最后面,然后执行类似于排序操作,将x与它左边(记为x-l)及上面(记为x-u)的数进行比较,根据比较结果有三种可能的操作:

  1. x-u > x 且x-u >= x-l  则将x 与 x-u进行交换;
  2. x-l > x 且x-l > x-u  则将x 与 x-l进行交换;
  3. x >= x-l 且 x > x-u  则x 不动,此时已经插入成功。

插入操作的过程如下:

 1 //Insert 算法要求首先把待插入的数值放在矩阵的右下角
 2 //即最后一行数据的最后一个空余位置
 3 bool insertElement(int newValue)
 4 {
 5     if(yangMatrix[ROW-1][COLUMN-1]!=MAX_VALUE)//数组已经满了
 6         return false;
 7 
 8     int row=ROW-1 ,column=COLUMN-1;
 9     yangMatrix[row][column]=newValue;
10 
11     int x_upper,x_left;
12     while(true)
13     {
14         if(row>0) 
15             x_upper=yangMatrix[row-1][column];
16         else
17             x_upper=MIN_VALUE;
18 
19         if(column>0) 
20             x_left=yangMatrix[row][column-1];
21         else
22             x_left=MIN_VALUE;
23 
24         if(x_upper>newValue&&x_upper>=x_left)//和上面的交换位置
25         {
26             yangMatrix[row][column]=x_upper;
27             yangMatrix[row-1][column]=newValue;
28             row--;
29         }
30         else if(x_left>newValue&&x_upper<x_left)//和左边的交换
31         {
32             yangMatrix[row][column]=x_left;
33             yangMatrix[row][column-1]=newValue;
34             column--;
35         }
36         else
37         {
38             break;
39         }
40     }
41     nextPosition++;
42     return true;
43 }
View Code

删除操作:

操作类似于插入操作,其时间复杂度也为O(m+n)。删除算法可以描述为,首先将删除的位置(x, y)的数字删除,然后调整,把杨氏矩阵中的最大值k(可以行为主序进行搜索到最后)填入到被删除位置,然后让此数与其下面的数(k-d)和右面的数进行(k-r)比较,此时比较结果为两种,因为此时元素一定会下移:

  1. k-d > k-r 将k-r 和 k进行交换
  2. k-d < k-r 将k-d 和 k进行交换  

删除操作如下所示:

 1 bool deleteElement(MyPoint p)
 2 {
 3     if(p.x>=ROW||p.y>=COLUMN)
 4     {
 5         return false;
 6     }
 7 
 8     //杨氏矩阵的最大值
 9     int maxElement=0;
10     int currentColumn,maxColumn,maxRow;
11     for (int i=0;i<ROW;i++)
12     {
13         currentColumn=COLUMN-1;
14         while(yangMatrix[i][currentColumn]==999)
15         {
16             currentColumn--;
17         }
18         if(maxElement<yangMatrix[i][currentColumn]){
19             maxElement=yangMatrix[i][currentColumn];
20             maxRow=i;
21             maxColumn=currentColumn;
22         }
23     }
24 
25     yangMatrix[maxRow][maxColumn]=MAX_VALUE; 
26     yangMatrix[p.x][p.y]=maxElement;//找出杨氏矩阵的最大值,然后填充到要删除的位置
27 
28     int x_right,x_bottom;
29     while(true)
30     {
31         if (p.x<ROW-1)
32             x_bottom=yangMatrix[p.x+1][p.y];
33         else
34             x_bottom=MAX_VALUE;
35 
36         if(p.y<COLUMN-1)
37             x_right=yangMatrix[p.x][p.y+1];
38         else
39             x_right=MAX_VALUE;
40 
41         if(x_right>x_bottom)
42         {
43             yangMatrix[p.x+1][p.y]=maxElement;
44             yangMatrix[p.x][p.y]=x_bottom;
45             p.x++;
46         }
47         else if(x_right<x_bottom)
48         {
49             yangMatrix[p.x][p.y+1]=maxElement;
50             yangMatrix[p.x][p.y]=x_right;
51             p.y++;
52         }
53         else
54         {
55             break;
56         }
57     }
58 
59     nextPosition--;
60     return true;
61 }
View Code

查找操作:

查找算法类似于BST二叉排序树,不过需要在其思想上稍微进行修改,才能满足杨氏矩阵的查找操作,同样利用杨氏矩阵的性质,不过此时应该换一个角度思考问题,因为与BST二叉排序树类比,所以应该从左下角开始看起,该元素的上面的元素比本身小和右面的元素比本身大,这样就与BST二叉排序树具有相同的性质。所以在查找时从左下角不断的比较,从而最终确定所查找元素位置。

查找操作如下所示:

 1 MyPoint * searchElement(int myValue)
 2 {
 3     MyPoint * point =(MyPoint*)malloc(sizeof(MyPoint));
 4     int row=ROW-1,column=0,temp1,temp2;
 5     while(yangMatrix[row][column]!=myValue){
 6         if (row<=0)
 7         {
 8             if(yangMatrix[row][column]>myValue){
 9                 if (column<COLUMN-1) column++;
10                 else 
11                     break;
12             }
13             else 
14                 break;
15         }
16         if (column>=COLUMN-1)
17         {
18             if(yangMatrix[row][column]<myValue){
19                 if (row>0) row--;
20                 else 
21                     break;
22             } 
23             else 
24                 break;
25         }
26         if(row>0&&column<COLUMN-1){
27             temp1=yangMatrix[row-1][column]-myValue;
28             temp2=yangMatrix[row][column+1]-myValue;
29             if(abs(temp1)>abs(temp2)){
30                 column++;
31             }else{
32                 row--;
33             }
34         }
35     }
36 
37     if(yangMatrix[row][column]!=myValue){
38         point->x=-1;
39         point->y=-1;
40     } else {
41         point->x=row;
42         point->y=column;
43     }
44     return point;
45 }
View Code


我自己动手写了一些插入、删除和查找的代码,全部的程序如下所示:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 /************************************************************************/
  5 /* 
  6 杨氏矩阵基本操作。
  7 首先介绍一下这个数据结构的定义,Young Tableau有一个m*n的矩阵,让后有一数组 a[k], 其中k<=m*n ,然后把a[k]中的数填入 m*n 的矩阵中,填充规则为:
  8 1.  每一行每一列都严格单调递增(有其他的版本是递减,其原理相同)。
  9 2.  如果将a[k]中的数填完后,矩阵中仍有空间,则填入 ∞。
 10 */
 11 /************************************************************************/
 12 #include <iostream>
 13 #include <string>
 14 using namespace std;
 15 #define ROW 4
 16 #define COLUMN 6
 17 #define MAX_VALUE 65535
 18 #define MIN_VALUE -65535
 19 
 20 int originalArray[]={1,    3,5,7,8,11,4,6,9,14,15,19,10,21,23,33,56,57,34,37,45,55};
 21 unsigned int yangMatrix[ROW][COLUMN]={MAX_VALUE};
 22 int nextPosition=0;
 23 
 24 struct MyPoint{
 25     int x;
 26     int y;
 27 };
 28 
 29 void printArray()
 30 {
 31     for (int i=0;i<ROW;i++)
 32     {
 33         for (int j=0;j<COLUMN;j++)
 34         {
 35             printf("%2d ",yangMatrix[i][j]);
 36         }
 37         printf("
");
 38     }
 39 }
 40 
 41 void initYangMatrix()
 42 {
 43     for (int i=0;i<ROW;i++)
 44     {
 45         for(int j=0;j<COLUMN;j++)
 46         {
 47             if(i*COLUMN+j<sizeof(originalArray)/sizeof(int))
 48                 yangMatrix[i][j]=originalArray[i*COLUMN+j];
 49             else
 50                 yangMatrix[i][j]=MAX_VALUE;
 51         }
 52     }
 53 }
 54 //Insert 算法要求首先把待插入的数值放在矩阵的右下角
 55 //即最后一行数据的最后一个空余位置
 56 bool insertElement(int newValue)
 57 {
 58     if(yangMatrix[ROW-1][COLUMN-1]!=MAX_VALUE)//数组已经满了
 59         return false;
 60 
 61     int row=ROW-1 ,column=COLUMN-1;
 62     yangMatrix[row][column]=newValue;
 63 
 64     int x_upper,x_left;
 65     while(true)
 66     {
 67         if(row>0) 
 68             x_upper=yangMatrix[row-1][column];
 69         else
 70             x_upper=MIN_VALUE;
 71 
 72         if(column>0) 
 73             x_left=yangMatrix[row][column-1];
 74         else
 75             x_left=MIN_VALUE;
 76 
 77         if(x_upper>newValue&&x_upper>=x_left)//和上面的交换位置
 78         {
 79             yangMatrix[row][column]=x_upper;
 80             yangMatrix[row-1][column]=newValue;
 81             row--;
 82         }
 83         else if(x_left>newValue&&x_upper<x_left)//和左边的交换
 84         {
 85             yangMatrix[row][column]=x_left;
 86             yangMatrix[row][column-1]=newValue;
 87             column--;
 88         }
 89         else
 90         {
 91             break;
 92         }
 93     }
 94     nextPosition++;
 95     return true;
 96 }
 97 
 98 bool deleteElement(MyPoint p)
 99 {
100     if(p.x>=ROW||p.y>=COLUMN)
101     {
102         return false;
103     }
104 
105     //杨氏矩阵的最大值
106     int maxElement=0;
107     int currentColumn,maxColumn,maxRow;
108     for (int i=0;i<ROW;i++)
109     {
110         currentColumn=COLUMN-1;
111         while(yangMatrix[i][currentColumn]==999)
112         {
113             currentColumn--;
114         }
115         if(maxElement<yangMatrix[i][currentColumn]){
116             maxElement=yangMatrix[i][currentColumn];
117             maxRow=i;
118             maxColumn=currentColumn;
119         }
120     }
121 
122     yangMatrix[maxRow][maxColumn]=MAX_VALUE; 
123     yangMatrix[p.x][p.y]=maxElement;//找出杨氏矩阵的最大值,然后填充到要删除的位置
124 
125     int x_right,x_bottom;
126     while(true)
127     {
128         if (p.x<ROW-1)
129             x_bottom=yangMatrix[p.x+1][p.y];
130         else
131             x_bottom=MAX_VALUE;
132 
133         if(p.y<COLUMN-1)
134             x_right=yangMatrix[p.x][p.y+1];
135         else
136             x_right=MAX_VALUE;
137 
138         if(x_right>x_bottom)
139         {
140             yangMatrix[p.x+1][p.y]=maxElement;
141             yangMatrix[p.x][p.y]=x_bottom;
142             p.x++;
143         }
144         else if(x_right<x_bottom)
145         {
146             yangMatrix[p.x][p.y+1]=maxElement;
147             yangMatrix[p.x][p.y]=x_right;
148             p.y++;
149         }
150         else
151         {
152             break;
153         }
154     }
155 
156     nextPosition--;
157     return true;
158 }
159 
160 MyPoint * searchElement(int myValue)
161 {
162     MyPoint * point =(MyPoint*)malloc(sizeof(MyPoint));
163     int row=ROW-1,column=0,temp1,temp2;
164     while(yangMatrix[row][column]!=myValue){
165         if (row<=0)
166         {
167             if(yangMatrix[row][column]>myValue){
168                 if (column<COLUMN-1) column++;
169                 else 
170                     break;
171             }
172             else 
173                 break;
174         }
175         if (column>=COLUMN-1)
176         {
177             if(yangMatrix[row][column]<myValue){
178                 if (row>0) row--;
179                 else 
180                     break;
181             } 
182             else 
183                 break;
184         }
185         if(row>0&&column<COLUMN-1){
186             temp1=yangMatrix[row-1][column]-myValue;
187             temp2=yangMatrix[row][column+1]-myValue;
188             if(abs(temp1)>abs(temp2)){
189                 column++;
190             }else{
191                 row--;
192             }
193         }
194     }
195 
196     if(yangMatrix[row][column]!=myValue){
197         point->x=-1;
198         point->y=-1;
199     } else {
200         point->x=row;
201         point->y=column;
202     }
203     return point;
204 }
205 
206 int main(){
207     initYangMatrix();
208     printf("After init:
");
209     printArray();
210 
211     nextPosition=sizeof(originalArray)/sizeof(int);
212 
213     int insertValue=2;
214     insertElement(insertValue);
215     printf("Insert a Value %d:
",insertValue);
216     printArray();
217 
218     struct MyPoint p={0,2};
219     deleteElement(p);
220     printf("After delete the position(%d,%d):
",p.x,p.y);
221     printArray();
222 
223     int searchVaule=24;
224     MyPoint *point=searchElement(searchVaule);
225     if(point->x==-1&&point->y==-1)
226         printf("Sorry, but %d is not in his Matrix.
",searchVaule);
227     else 
228         printf("The value %d's location is:position(%d,%d).
",searchVaule,point->x,point->y);
229 
230     searchVaule=23;
231     point=searchElement(searchVaule);
232     if(point->x==-1&&point->y==-1)
233         printf("Sorry, but %d is not in his Matrix.
",searchVaule);
234     else 
235         printf("The value %d's location is:position(%d,%d).
",searchVaule,point->x,point->y);
236 
237     return 0;
238 }
View Code
原文地址:https://www.cnblogs.com/havePassed/p/3560170.html