《算法导论》第6章 堆排序 (4)Young氏矩阵
1. 什么是Young氏矩阵?
一个 m * n 的矩阵,其中每一行的数据都从左到右排序,每一列的数据都从上到下排序。
其中用 ∞ 代表不存在的元素,一共可以存放 r ≤ mn 个有限的数。
如下面程序实现中用来测试的Young氏矩阵:
{ 1, 3, 5, 7, 8, 11 }
{ 4, 6, 9, 14, 15, 19 }
{ 10, 21, 23, 33, 56, 57 }
{ 34, 37, 45, 55, ∞, ∞ }
{ 4, 6, 9, 14, 15, 19 }
{ 10, 21, 23, 33, 56, 57 }
{ 34, 37, 45, 55, ∞, ∞ }
2. 相关问题及思路
2.1 实现EXTRACT-MIN的算法,使其运行时间为O(m + n)。
参考最大堆的方法MAX-HEAPIFY,两者的相似性是:一个元素 i 的改变,破坏了
堆和Young氏矩阵的性质。MAX-HEAPIFY从 i 的左右子结点中选出最大者 j ,
拷贝到被取出的 i 的位置。这样 j 处的性质又被破坏,然后递归地继续处理这个结点位置。
EXTRACT-MIN也可以这样处理,思路是相同的。
两个问题都可以归纳为:根结点被取出后,数据结构性质被破坏,递归地进行局部调整。
2.2 查找一个元素在矩阵中是否存在。
需要从右上角的元素开始向左向下遍历,比如上面矩阵中的元素11。
假如要查找14,14比11大则向下继续比较,14比19小则向左走。
不能从左上角的元素1开始遍历,因为向右的3和向下的4都比1大,没法决定往哪个方向遍历。
3. 代码实现及注释
#include <stdio.h> // 与MAX-HEAPIFY很像,找出右边元素和下边元素中的较小者, // 如果没处理到边界,就继续递归处理。 void youngify(int matrix[][6], int row, int col, int i, int j) { int minI, minJ; if (i < row - 1) { minI = i + 1; minJ = j; } else { minI = i; minJ = j; } if (j < col - 1 && matrix[i][j + 1] < matrix[minI][minJ]) { minI = i; minJ = j + 1; } if (minI != i || minJ != j) { matrix[i][j] = matrix[minI][minJ]; youngify(matrix, row, col, minI, minJ); } } int extract_min(int matrix[][6], int row, int col) { int min = matrix[0][0]; youngify(matrix, row, col, 0, 0); return min; } // 从最右上角开始,比要搜索元素x大则向左, // 比要x小则向下。 int search(int matrix[][6], int row, int col, int x) { int i = 0; int j = col - 1; while (i < row && j >= 0) { if (matrix[i][j] == x) return 1; else if (matrix[i][j] > x) j--; else i++; } return 0; } void printMatrix(int matrix[][6], int row, int col) { int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) printf("%d, ", matrix[i][j]); printf("\n"); } printf("\n"); } int main(void) { int matrix[][6] = { { 1, 3, 5, 7, 8, 11 }, { 4, 6, 9, 14, 15, 19 }, { 10, 21, 23, 33, 56, 57 }, { 34, 37, 45, 55, 100, 100 } }; extract_min(matrix, 4, 6); printMatrix(matrix, 4, 6); printf("%d\n", search(matrix, 4, 6, 46)); printf("%d\n", search(matrix, 4, 6, 21)); return 1; }