数组之三种矩阵

文字描述

矩阵的压缩:对于某些特殊的矩阵来说,非零元素较少,大部分元素为0,采用某种算法,将非零元素存储在一位数组里以达到节省存储空间的目的的过程,称为矩阵的压缩

 

矩阵的还原:将压缩后的数组还原成原始矩阵的过程

1、对角矩阵

①矩阵介绍

所谓对角矩阵:

矩阵中的所有非零元素都集中在以主对角线为中心的带状区域中,

 

即除了主对角线上和直接在主对角线上下若干条对角线上的元素外,其余元素均为零。

 

这样的矩阵称为半带宽为d的带状矩阵,带宽是2*d+1,d为直接在对角线上下方不为0的对角线数

② 矩阵压缩原理

 

对于n阶2d+1对角矩阵,只需要存放对角线区域内 n*(2*d+1)-d*(d+1)个非零元素

为了简便运算,认为每一行都有2*d+1个元素,若少于2*d+1个元素,则添零补齐。

因为非零元素都在主对角线元素的左右两侧,

那么只要在矩阵的每一行的主对角线元素的两侧分别  “凑够”  d个元素即可,

 

如果该元素  “不在"  矩阵内部,则补零,如果“在”矩阵内部,则存储到一维数组中即可

 

2、对称矩阵

① 矩阵介绍

对称矩阵  array[ i ][ j ]=array[ j ][ i ]  所以对于相同的元素只保存一个

②矩阵压缩的原理

压缩成一个一维数组后 array [ i ]  [ j]  =array [ j ]  [ i  ]

 

s [ k ] = i * ( i + 1 ) / 2 + j = j * ( j + 1  ) / 2 + i ;

 

对于一个n阶的矩阵而言,压缩后一维空间的数目为  n*(n+1)/2;

3、三角矩阵

① 矩阵介绍

所谓三角矩阵:

整个矩阵只有主对角线及主对角线以上(或以下)为非零元素。

 

下三角形矩阵:主对角线及主对角线以下为非零元素

 

上三角形矩阵:主对角线及主对角线以上为非零元素

 

很显然对于一个n阶的矩阵而言,压缩后一维空间的数目为n*(n+1)/2;(等差数列求和)

 

(以下以下三角为例进行分析)

② 矩阵压缩的原理

根据该矩阵的性质,很容易得出结论

 

很显然第一行一个元素,第二行两个元素,依次类推。。。

代码实现

1、对角矩阵

import org.Stone6762.Utils.ArrayUtils;

/** 
* @Stone6762 
*/ 
public class DiagonalArray {

/** 
* @Title: compress n阶2d+1对角矩阵的压缩 
* @Description: TODO(n阶2d+1对角矩阵的压缩) 
* @param oriArray 
* 原始矩阵 
* @param d 
* 半带宽 
* @return 
*/ 
public static double[] compress(double[][] oriArray, int d) { 
int n = oriArray.length; 
double compressedArray[] = new double[n * (2 * d + 1)]; 
int col = 0; 
for (int i = 0, k = 0; i < n; i++) { 
for (int j = -d; j <= d; j++, k++) { 
col = i + j;//计算对应的列值 
if (col >=0 && col < n) {//在矩阵内部的就赋值,不在矩阵内部的就直接补零 
compressedArray[k] = oriArray[i][col]; 



return compressedArray; 
}

/** 
* @Title: recover n阶2d+1对角矩阵的还原 
* @Description: TODO() 
* @param compressedArray 
* 压缩后的矩阵 
* @param d 
* 半带宽 
* @return 
*/ 
public static double[][] recover(double[] compressedArray, int d) { 
int sum = compressedArray.length; 
int n = sum / (2 * d + 1); 
double[][] oriArray = new double[n][n]; 
int col = 0; 
for (int i = 0, k = 0; i < n; i++) { 
for (int j = -d; j <= d; j++, k++) { 
col = i + j; 
if (col >= 0 && col < n) { 
oriArray[i][col] = compressedArray[k]; 



return oriArray; 
}

public static void main(String[] args) { 
double[][] arr = { 
{ 1, 2, 0, 0, 0 }, 
{ 3, 4, 5, 0, 0 }, 
{ 0, 6, 7, 8, 0 }, 
{ 0, 0,9,10,11 }, 
{ 0, 0, 0,12, 13 }

};

double[] tar = compress(arr,1); 
// [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 0.0]

ArrayUtils.printOneArray(tar);

ArrayUtils.printMulArray(recover(tar,1));

}

}


2、对称矩阵

import org.Stone6762.Utils.ArrayUtils;

/** 
* @Stone6762 
*/ 
public class SymmetricalArray {

/** 
* @Title: compressSymmetricalArray 对称矩阵的压缩 
* @Description: TODO(n阶方阵 对称矩阵(a[i][j]=a[j][i])的压缩 此处采用的的是行优先顺序储存的方式) 
* @param <T> 
* @param oriArray 
* @return 
*/ 
public static double[] compress(double[][] oriArray) { 
int n = oriArray.length; 
double compressedArray[] = new double[n * (n + 1) / 2]; 
for (int i = 0; i < oriArray.length; i++) { 
for (int j = 0; j <= i; j++) { 
compressedArray[i * (i + 1) / 2 + j] = oriArray[i][j]; 


return compressedArray; 
}

/** 
* @Title: recoverSymmetricalArray 
* @Description: TODO( 将压缩后的对称矩阵进行还原) 
* @param compressedArray 
* @return 
*/ 
public static double[][] recover(double[] compressedArray) { 
int length = compressedArray.length; 
int n = (int) Math.sqrt(2 * length); 
double[][] oriArray = new double[n][n]; 
for (int i = 0, k = 0; i < oriArray.length; i++) { 
for (int j = 0; j <= i; j++, k++) { 
oriArray[j][i] = oriArray[i][j] = compressedArray[k]; 


return oriArray; 
}

public static void main(String[] args) { 
double[][] arr = { 
{ 1, 2, 3 }, 
{ 2, 4, 6 }, 
{ 3, 6, 5 } };

double[] tar = compress(arr); 
// [1.0, 2.0, 4.0, 3.0, 6.0, 5.0]

ArrayUtils.printOneArray(tar);

ArrayUtils.printMulArray(recover(tar));

}

}


3、三角矩阵

import org.Stone6762.Utils.ArrayUtils;

/** 
* @Stone6762 
*/ 
public class TriangleArray {

/** 
* @Title: compress 
* @Description: TODO(以下三角形为例压缩) 
* @param oriArray 
* @return 
*/ 
public static double[] compress(double[][] oriArray) { 
int n = oriArray.length; 
double compressedArray[] = new double[n * (n + 1) / 2]; 
for (int i = 0; i < oriArray.length; i++) { 
for (int j = 0; j <= i; j++) { 
compressedArray[i * (i + 1) / 2 + j] = oriArray[i][j]; 


return compressedArray; 
}

/** 
* @Title: recover 
* @Description: TODO(以下三角形为例解压) 
* @param compressedArray 
* @return 
*/ 
public static double[][] recover(double[] compressedArray) { 
int length = compressedArray.length; 
int n = (int) Math.sqrt(2 * length); 
double[][] oriArray = new double[n][n]; 
for (int i = 0, k = 0; i < oriArray.length; i++) { 
for (int j = 0; j <= i; j++, k++) { 
oriArray[i][j] = compressedArray[k]; 


return oriArray; 
}

public static void main(String[] args) { 
double[][] arr = { 
{ 1, 0, 0 }, 
{ 2, 4, 0 }, 
{ 3, 6, 5 } }; 
double[] tar = compress(arr); 
// [1.0, 2.0, 4.0, 3.0, 6.0, 5.0]

ArrayUtils.printOneArray(tar);

ArrayUtils.printMulArray(recover(tar));

}

}

提醒:各种矩阵实现源码下载:

http://www.cnblogs.com/tanlon/p/4155687.html

时间: 2024-10-16 11:10:30

数组之三种矩阵的相关文章

(转载)Android之三种网络请求解析数据(最佳案例)

[置顶] Android之三种网络请求解析数据(最佳案例) 2016-07-25 18:02 4725人阅读 评论(0) 收藏 举报  分类: Gson.Gson解析(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 小武:相信大家都用过网络请求解析数据,只是方法不一样而已,但是,逻辑都是差不多的: 一:AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个

图像处理之三种常见双立方插值算法

http://blog.csdn.net/jia20003/article/details/40020775 图像处理之三种常见双立方插值算法 双立方插值计算涉及到16个像素点,其中(i', j')表示待计算像素点在源图像中的包含 小数部分的像素坐标,dx表示X方向的小数坐标,dy表示Y方向的小数坐标.具体 可以看下图: 根据上述图示与双立方插值的数学表达式可以看出,双立方插值本质上图像16个像素点 权重卷积之和作为新的像素值. 其中R(x)表示插值表达式,可以根据需要选择的表达式不同.常见有基

(转)详解LVS负载均衡之三种工作模型原理和10种调度算法

前言:最近在为我们的产品在做高可用,一边搭环境,一边了解相关知识,搜到这篇博客,质量不错,表述清晰,于是转载过来学习. 标签:详解LVS负载均衡之三种工作模型原理和10种调度算法 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://linuxnx.blog.51cto.com/6676498/1195379 LVS负载均衡原理和算法详解    Internet的快速增长使多媒体网络服务器面对的访问数量快速增加,服务器需要具备提供大

数组-09. 求矩阵的局部极大值

数组-09. 求矩阵的局部极大值(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 徐镜春(浙江大学) 给定M行N列的整数矩阵A,如果A的非边界元素A[i][j]大于相邻的上下左右4个元素,那么就称元素A[i][j]是矩阵的局部极大值.本题要求给定矩阵的全部局部极大值及其所在的位置. 输入格式: 输入在第1行中给出矩阵A的行数M和列数N(3<=M,N<=20):最后M行,每行给出A在该行的N个元素的值.数字间以空格分隔.

(转)NGUI研究院之三种方式监听NGUI的事件方法

NGUI事件的种类很多,比如点击.双击.拖动.滑动等等,他们处理事件的原理几乎万全一样,本文只用按钮来举例. 1.直接监听事件 把下面脚本直接绑定在按钮上,当按钮点击时就可以监听到,这种方法不太好很不灵活. 1 2 3 4 void OnClick() { Debug.Log("Button is Click!!!"); }   2.使用SendMessage 选择按钮后,在Unity导航菜单栏中选择Component->Interaction->Button Messag

OC中动态创建可变数组的问题.有一个数组,数组中有13个元素,先将该数组进行分组,每3个元素为一组,分为若干组,最后用一个数组统一管理这些分组.(要动态创建数组).两种方法

<span style="font-size:24px;">//////第一种方法 // NSMutableArray *arr = [NSMutableArray array]; // for (int i = 0; i < 13; i ++) { // [arr addObject:[NSString stringWithFormat:@"lanou%d",i + 1]]; // } // NSLog(@"%@",arr);

stream转byte数组几种方式

第一种,写法最简单的.使用原生IO,一个字节一个字节读: //一个字符一个字符读,太慢 int i; while((i=in.read()) != -1){ i = in.read(); arr[j++] = i; } 这种方式非常的慢,极为不推荐. 第二种,一次读完: byte[] arr = new byte[in.available()]; in.read(arr); 这种和第一种相反,一次读完流,这种情况在文件稍大时会非常占用内存,也极为不推荐. 第三种,缓冲读: byte[]buff

Python使用np.c_和np.r_实现数组转换成矩阵

# -*- coding: utf-8 -*-"""Created on Sat Jun 30 14:49:22 2018 @author: zhen""" import numpy as npa = np.array([[1,2,3],[11,22,33]])b = np.array([[4,5,6],[44,55,66]])# 数组连接成矩阵c = np.c_[a,b]r = np.r_[a,b]print('-------------按行转

爬虫学习 05.Python网络爬虫之三种数据解析方式

爬虫学习 05.Python网络爬虫之三种数据解析方式 引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据解析.因为大多数情况下的需求,我们都会指定去使用聚焦爬虫,也就是爬取页面中指定部分的数据值,而不是整个页面的数据.因此,本次课程中会给大家详细介绍讲解三种聚焦爬虫中的数据解析方式.至此,我们的数据爬取的流程可以修改为: 指定url 基于r