Young氏矩阵
一个 m x n 的Young氏矩阵是指,每一行数据都是从左到右排好序,每一列的数据也都是从上到下排好序。其中也可能存在一些INF的数据,表示不存在的元素,一个mxn的Young氏矩阵最多用来存放 r <= mn个元素。
详细见《算导》P.83
Young氏矩阵类似于堆的结构,主要实现的API包括以下:
1. void insert(int x)
功能:将一个元素x插入到矩阵中,复杂度O(m+n)
算法过程:
1) 判断矩阵是否为Full
2) 如果不为Full,插入元素到矩阵的右下角(row, col)位置,然后进行swim(row, col)将元素移动到合适位置。
2. int getMin()
功能:返回矩阵中的最小值,复杂度O(1)
算法过程:
1) 判断矩阵是否为Empty
2) 直接返回mat[0][0].左上角元素,依据矩阵的性质
3. int delMin()
功能:返回矩阵中的最小值,并把它从矩阵中删除,复杂度O(m+n)
算法过程:
1) 判断矩阵是否为Empty
2) 暂存mat[0][0]元素用于返回,把矩阵最右下角的元素放到mat[0][0],使用sink(0, 0)进行下沉调整元素到合适位置
4. bool seach(int x)
功能:判断矩阵是否存在元素x,复杂度O(m+n)
算法过程:
版本1:通过递归的方式,比较当前mat[x][y] 和 key的关系,将划分到是否需要在(m-1)x(n)子矩阵和mx(n-1)子矩阵进行递归查找
版本2:初始位置为矩阵右上角,如果当前元素大于key,向左移动,如果当前元素小于key向下移动。
5. void sort()
功能:对矩阵元素进行排序,对矩阵执行元素个数次的delMin()操作就可以得到排序结果。复杂度O(n*m*(n+m))
辅助函数:
==两个函数的实现与实现堆的swim和sink操作思想完全一样==
void swim(int i, int j)
功能:对(i, j)位置元素进行上浮操作,与(i-1, j) 和 (i, j-1)位置的元素进行比较,与他们之间的最大值进行交换
void sink(int i, int j)
功能:对(i, j)位置元素进行下沉操作,与(i+1, j) 和 (i, j+1)位置的元素进行比较, 与他们之间的最小值进行交换
完整代码如下:
const int INF = 0x3fffffff; class YoungMatrix {
public:
YoungMatrix(int row, int col); // constructor
~YoungMatrix(); // destructor void insert(int x); // insert a element
int delMin(); // delete and return the minimal element
bool search(int x, int version = 1); // search a element
int getMin(); // return the minimal element
// sort(); // 调用 n*n delMin()得到结果n*n*(n+n) O(n^3) // print the matrix
void printMatrix() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
cout << mat[i][j] << "\t";
cout << endl;
}
cout << endl;
} /*** auxiliary function ***/
private:
void swim(int i, int j); // swim the element at (i, j), 从右下角上升到左上角
void sink(int i, int j); // sink the element at (i, j), 从左上角下沉到右下角
bool searchHelp1(int x, int y, int key); // recursive function to search the element, divide the problem into sub-matrix (m, n-1) and (m-1, n)
bool searchHelp2(int key); // init the position in (0, col-1). like go down the stairs from right to left private:
int **mat;
int row, col;
int num;
}; YoungMatrix::YoungMatrix(int row, int col) {
this->num = 0;
this->row = row;
this->col = col;
mat = new int*[row];
for (int i = 0; i < row; i++)
mat[i] = new int[col];
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = INF;
} YoungMatrix::~YoungMatrix() {
for (int i = 0; i < row; i++)
delete[] mat[i];
delete[] mat;
} void YoungMatrix::swim(int i, int j) {
while (true) {
int v = mat[i][j], p = -1;
if (i - 1 >= 0 && v < mat[i - 1][j]) { v = mat[i - 1][j], p = 0; }
if (j - 1 >= 0 && v < mat[i][j - 1]) { v = mat[i][j - 1]; p = 1; } if (p == -1) break; if (p == 0) {
swap(mat[i - 1][j], mat[i][j]);
i -= 1;
}
else {
swap(mat[i][j - 1], mat[i][j]);
j -= 1;
}
}
} void YoungMatrix::sink(int i, int j) {
while (true) {
int v = mat[i][j], p = -1;
if (i + 1 < row && v > mat[i + 1][j]) { v = mat[i + 1][j], p = 0; }
if (j + 1 < col && v > mat[i][j + 1]) { v = mat[i][j + 1]; p = 1; } if (p == -1) break; if (p == 0) {
swap(mat[i + 1][j], mat[i][j]);
i += 1;
}
else {
swap(mat[i][j + 1], mat[i][j]);
j += 1;
}
}
} void YoungMatrix::insert(int x) {
// is full?
if (num == col * row) {
cerr << "Error: the matrix is full" << endl;
return;
} // put at the last position
this->num++; int i = row - 1, j = col - 1;
mat[i][j] = x;
swim(i, j);
} int YoungMatrix::getMin() {
if (this->num > 0) return mat[0][0];
else {
cerr << "Error: The matrix is empty" << endl;
return -1;
}
} int YoungMatrix::delMin() {
if (this->num <= 0) {
cerr << "Error: The matrix is empty" << endl;
return -1;
} else {
int ret = mat[0][0];
mat[0][0] = mat[row - 1][col - 1];
this->num--;
sink(0, 0);
return ret;
}
} bool YoungMatrix::search(int x, int version) {
if (this->num <= 0) return false;
if (version == 1) {
return searchHelp1(0, 0, x);
} else {
return searchHelp2(x);
}
} bool YoungMatrix::searchHelp1(int x, int y, int key) {
if (x >= row || y >= col) return false;
if (mat[x][y] < key) return searchHelp1(x + 1, y, key) || searchHelp1(x, y + 1, key);
else if (mat[x][y] > key) return false;
else return true;
} bool YoungMatrix::searchHelp2(int key) {
int i = 0, j = col - 1;
while (true) {
if (i >= row || j >= col) return false;
if (mat[i][j] == key) return true;
else if (mat[i][j] < key) i++;
else if (mat[i][j] > key) j--;
}
}
测试代码:
#include "YoungMatrix.h"
using namespace std; int a[] = { 9, 16, 3, 2, 4, 8, 5, 14, 12 }; int main(int argc, char** argv) {
YoungMatrix ym(4,4);
int e;
for (int i = 0; i < 9; i++) {
ym.insert(a[i]);
}
ym.printMatrix();
cout << "search result: " << ym.search(2, 2) << endl;
cout << ym.delMin() << endl;
cout << "search result: " << ym.search(2, 2) << endl;
ym.printMatrix();
return 0;
}
Young氏矩阵的更多相关文章
- 算法导论 第六章 思考题6-3 Young氏矩阵
这题利用二叉堆维持堆性质的办法来维持Young氏矩阵的性质,题目提示中写得很清楚,不过确实容易转不过弯来. a,b两问很简单.直接看c小问: 按照Young氏矩阵的性质,最小值肯定在左上角取得,问题在 ...
- 十一、从头到尾彻底解析Hash 表算法
在研究MonetDB时深入的学习了hash算法,看了作者的文章很有感触,所以转发,希望能够使更多人受益! 十一.从头到尾彻底解析Hash 表算法 作者:July.wuliming.pkuoliver ...
- 第6章 堆排序,d叉堆,优先队列
#include<stdio.h> #include<stdlib.h> #include<string.h> #define leftChild(i) (2*(i ...
- Hession矩阵(整理)
二阶偏导数矩阵也就所谓的赫氏矩阵(Hessian matrix). 一元函数就是二阶导,多元函数就是二阶偏导组成的矩阵. 求向量函数最小值时用的,矩阵正定是最小值存在的充分条件. 经济学中常常遇到求最 ...
- KCF跟踪算法
参考:https://www.cnblogs.com/YiXiaoZhou/p/5925019.html 参考:https://blog.csdn.net/shenxiaolu1984/article ...
- 【杨氏矩阵+勾长公式】POJ 2279 Mr. Young's Picture Permutations
Description Mr. Young wishes to take a picture of his class. The students will stand in rows with ea ...
- 杨氏矩阵:查找x是否在矩阵中,第K大数
参考:http://xudacheng06.blog.163.com/blog/static/4894143320127891610158/ 杨氏矩阵(Young Tableau)是一个很奇妙的数据结 ...
- 杨氏矩阵定义及其查找的实现C++
先介绍一下这个数据结构的定义,Young Tableau有一个m*n的矩阵,然后有一数组 a[k], 其中 k<=m*n ,然后把a[k]中的数填入 m*n 的矩阵中,填充规则为: 1. 每一 ...
- paper 114:Mahalanobis Distance(马氏距离)
(from:http://en.wikipedia.org/wiki/Mahalanobis_distance) Mahalanobis distance In statistics, Mahalan ...
随机推荐
- java 单例设计模式
1.饿汉单例设计模式: 步骤 : 1.定义一个私有的静态成员变量来引用对象(私有的静态对象),设置对象唯一. 2.私有化构造方法,防止new对象. 3.创建一个公开的静态方法,返回上面的 ...
- 在linux下获取帮助
1.使用man手册页 man是一种显示Unix/Linux在线手册的命令.可以用来查看命令.函数或文件的帮助手册,另外它还可以显示一些gzip压缩格式的文件. 读者在遇到不懂的命令时,可以用man查看 ...
- innerText引发的错误
因为firefox对innerText的不支持,所以以下代码在firefox里运行有错误. //重新加载饼图 ") { var gridView = document.getElementB ...
- .net实现调用本地exe等应用程序的办法总结
根据客户需求用户要实现在一个BS系统上打开本地的一应用程序,在网上查了好多资料再加上自己的各种测试,到最后功能是实现了,只不过还存在一些问题,接下来会先把各种方法一一列举出来 1.先写最终测试通过的这 ...
- Excel jxl导入导出
JAVA EXCEL API简介 Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Wind ...
- form 编译命令
11i: Form:f60gen $AU_TOP/forms/ZHT/GLXJEENT.fmb userid=apps/tpsadbm output_file=$GL_TOP/forms/ZHT/GL ...
- Hadoop HDFS编程 API入门系列之从本地上传文件到HDFS(一)
不多说,直接上代码. 代码 package zhouls.bigdata.myWholeHadoop.HDFS.hdfs5; import java.io.IOException; import ja ...
- python之fabric(二):执行模式(转)
执行模式 执行模式可以让你在多个主机上执行多个任务. 执行策略: 默认fabric是单个有序地执行方法,其行为如下: 1. 创建一系列任务,通过fab任务执行要执行的任务: 2. 根据主机列表定义,去 ...
- markdown 的基本操作
文档 http://mux.alimama.com/posts/620?spm=0.0.0.0.4VVnvp http://www.jianshu.com/p/1e402922ee32/ MdChar ...
- expdp\impdp及exp\imp
数据泵文件 expdp介绍 EXPDP命令行选项1. ATTACH该选项用于在客户会话与已存在导出作用之间建立关联.语法如下ATTACH=[schema_name.]job_nameSchema_na ...