CLRS 6-3 :Young氏矩阵( 杨氏矩阵)
解答:
(a)2 4 9 12
3 5 14 Max
8 16 Max Max
Max Max Max Max
(b)Y[1, 1]为Max的话,那么按照Young氏矩阵定义,矩阵中其他数值必然大于等于它,所以Y为空。
若Y[m, n] < Max的话,由其他元素都小于等于Y[m, n]可知此矩阵是满的。
(c)算法思想:
1)A[0][0]必然是最小值,将其取出,然后将矩阵的最后一个元素A[m-1[n-1]补到第一位来,并将A[m-1[n-1]设置为Max
2)将A[0][0]与A[0][1]和A[1][0]二者之间的最小值进行交换,
3)若交换的是A[0][1],则在下一步对m*(n-1)矩阵的第一个元素重复2,
若交换的是A[1][0],则在下一步对(m-1)*n矩阵的第一个元素重复2
总之每次总是将第一个元素与其周边元素进行比较而已。
using namespace std;
// 假设MAX为无穷大
#define MAX 1000000
int extract_min( int ** a, int m, int n);
void young_matrixify( int ** a, int i, int j, int m, int n);
int main()
{
int a[ 4 ][ 4 ] = { 2 , 4 , 9 , 12 , 3 , 5 , 14 , MAX, 8 , 16 , MAX, MAX, MAX, MAX, MAX, MAX};
// 打印数组a,可以看出它符合young氏矩阵的定义
for ( int i = 0 ; i < 4 ; i ++ )
{
for ( int j = 0 ; j < 4 ; j ++ )
cout << a[i][j] << " \t " ;
cout << endl;
}
int ** b = new int * [ 4 ];
for ( int i = 0 ; i < 4 ; i ++ )
b[i] = new int [ 4 ];
for ( int i = 0 ; i < 4 ; i ++ )
{
for ( int j = 0 ; j < 4 ; j ++ )
b[i][j] = a[i][j];
}
// 第一次取出最小值
extract_min(b, 4 , 4 );
// 打印取出最小值之后的young氏矩阵
for ( int i = 0 ; i < 4 ; i ++ )
{
for ( int j = 0 ; j < 4 ; j ++ )
cout << b[i][j] << " \t " ;
cout << endl;
}
// 再次取出最小值
extract_min(b, 4 , 4 );
// 打印取出最小值之后的young氏矩阵
for ( int i = 0 ; i < 4 ; i ++ )
{
for ( int j = 0 ; j < 4 ; j ++ )
cout << b[i][j] << " \t " ;
cout << endl;
}
return 0 ;
}
int extract_min( int ** a, int m, int n)
{
int temp = a[ 0 ][ 0 ];
a[ 0 ][ 0 ] = a[m - 1 ][n - 1 ];
a[m - 1 ][n - 1 ] = MAX;
young_matrixify(a, 0 , 0 , m, n);
return temp;
}
// 分了四种情况进行讨论,以i,j是否到达边界为区分点
void young_matrixify( int ** a, int i, int j, int m, int n)
{
if (i < m && j < n)
{
int ii = i;
int jj = j;
if (i + 1 < m && j + 1 < n && a[i + 1 ][j] > a[i][j + 1 ])
{
int temp = a[i][j];
a[i][j] = a[i][j + 1 ];
a[i][j + 1 ] = temp;
jj = j + 1 ;
}
else if (i + 1 < m && j + 1 < n && a[i + 1 ][j] < a[i][j + 1 ])
{
int temp = a[i][j];
a[i][j] = a[i + 1 ][j];
a[i + 1 ][j] = temp;
ii = i + 1 ;
}
else if (i + 1 < m && j + 1 == n && a[i + 1 ][j] < a[i][j])
{
int temp = a[i][j];
a[i][j] = a[i + 1 ][j];
a[i + 1 ][j] = temp;
ii = i + 1 ;
}
else if (j + 1 < n && i + 1 == m && a[i][j + 1 ] < a[i][j])
{
int temp = a[i][j];
a[i][j] = a[i][j + 1 ];
a[i][j + 1 ] = temp;
jj = j + 1 ;
}
if (ii != i || jj != j)
young_matrixify(a, ii, jj, m, n);
}
}
(d)其实插入与(c)中的取出操作大同小异,将插入元素放入未满位置,然后比较相邻元素,直至相邻元素都比它小。
(e)所有的数首先插入到矩阵中所用时间为n^2*O(2n),然后取出操作为n^2*O(2n),加起来化简之后即为O(n^3)。
(f)算法思想:
从A[m-1][0],即左下角开始寻找,比较相邻元素,然后不断循环至m*(n-1)或(m-1)*n矩阵,画画图就很明了了。
下列代码加入上面代码中即可。
bool find( int ** a, int goal, int m, int n)
{
int mm = m;
int nn = n;
while (m > 0 && n > 0 )
{
if (a[m - 1 ][nn - n] == goal)
{
return true ;
}
else if (a[m - 1 ][nn - n] > goal)
-- m;
else if (a[m - 1 ][nn - n] < goal)
-- n;
}
return false ;
}