6.1 6.2 数组、稀疏矩阵
来源:互联网 发布:彩虹timez知乎 编辑:程序博客网 时间:2024/05/16 11:03
数组
数组的一般定义
数组是一种由相同数据类型构成的序列。数组的本质就是一个线性表。对于一维数组,该线性表中的元素类型就是需要存放的类型ElementType
,对于多维数组,其维度
对于数组来说,通常只有以下两种操作:读取和写入。这两种操作需要一个输入向量来表示下标(即用来定位)。
数组中最常见的是一维数组和二维数组,分别可以对应线性代数中的向量(vector)和矩阵(matrix)。
在教材采用的C/C++语言中,可以很自然的使用形如int A[10]
这样的语句来定义一个数组。对于这样定义的数组,其长度是定长的,不允许在运行时改变。这样的数组定义也只能出现在栈内存区或者全局内存区。C99标准支持int n = 10; int A[n];
这样的用法,但是C++11标准不支持(因为STL容器是一个更好的替代)。对于堆内存的数组,可以使用指针,如int * A = (int *)malloc(sizeof(int) * 10);
来创建一个数组(指针指向数组的首地址);实际上,利用这种方式包装好一个容器,例如STL的std::vector
类,是更方便、更安全、更有效率的。顺带一提,STL的std::vector
类不支持直接存放二维(多维)数组,只能使用vector<vector<int>>
这种类似的方式进行存放。这样在使用push_back
方法将新的一维数组压入容器,可能存在反复执行构造函数的开销;对于C++11可以使用右值语义(R-Value)和std::move
以尽量减小这个问题带来的效率损失。
数组的存储结构
数组是一种线性表,因此需要连续的存放在存储器的相应位置。对于一维数组的存储结构,其实比较简单。在C/C++语言中,只需要一个指针指向数组的首地址,就能够表示一个数组。当然,必须要有一个标记,来指示数组的结束(例如使用length
字段标识数组的长度,亦或C风格字符串的\0
结束符)。
因此,对于一个一维数组A
,其元素A[i]
(按照C/C++的习惯i从0开始)的实际地址
而对于一个二维数组,其输入是一个二元组,因此需要设法构造出一种映射,将其映射在存储器的连续的相应位置。常用的方法有行优先和列优先。
对于一个二维数组A[m][n]
,行优先是指,A[i]
取出的元素,是表示第A[i]
表示的是第i
列的一个一维数组。因此不难得出下面的计算公式:对于A[m][n]
,A[i][j]
元素的位置
行优先:
列优先:
C/C++的编译器默认按照行优先存放。
最后需要提及的是,并不是所有语言的数组都是使用一串连续存储空间实现的。之前提及过的PHP的数组,是使用的哈希表来处理键值对(字符串类型的键也可以作为数组的下标)。
数组与特殊矩阵
矩阵可以使用二维数组进行存储。对于特殊形式的矩阵(对称阵、上下三角阵),只需要存储一半的元素就可以了。
常见的存储映射是,将二维降维,映射在一维数组上。以下三角阵为例,对于
总之,特殊矩阵的存储,在于根据问题的情况找到一个合适的映射(能在
稀疏矩阵
首先给出稀疏矩阵的一个定义:一个
稀疏矩阵的非零元分布具有随机性,因此不能简单作之前的映射。因此可以用键值对的线性表,来描述一个稀疏矩阵。
这里的键值对可以使用std::pair<std::pair<int, int>, ElementType>
来表示,也可以使用C++11的std::tuple<int, int, ElementType>
这个三元组类来表示。这里我更倾向使用键值对的表示,前一个pair
作为二元输入向量,而外层的pair
的第二个元素作为下标为输入向量的位置的值。
因此可以用std::vector<std::pair<std::pair<int, int>, ElementType>>
来表示一个稀疏矩阵。
初始情况下,这个线性表容器是空的,表示这个矩阵是零矩阵
对于一个稀疏矩阵而言,其赋值操作的最坏运行时间取决于非零元的个数std::map
还是std::unordered_map
都是会造成大量空间浪费,违背了稀疏矩阵的初衷。
一道不错的实验题
已知一个二维数组
最原始的办法是进行朴素搜索,需要
说起来很简单,但是编码还是很有难度的。尤其是第一层二分时,当元素不能在这一行时,必然满足小于第一个元素或者大于最后一个元素。除此之外,lower_bound
返回的是不小于指定值的最小下标。因此需要判断返回的值是否等于需要查找的值。
//Not Found Constant Defineconst std::pair<int, int> not_found(-1, -1);/*** @brief 查找二维数组中指定元素的位置* @param std::vector<std::vector<int>> & matrix 输入矩阵* @param int val 待查找元素的值* @return std::pair<int, int> 返回二元组表示的元素的位置*/std::pair<int, int> matrix_find(std::vector<std::vector<int> > & matrix, int val) { //利用有序性二分查找,M*N矩阵,平均时间复杂度O(logM+logN) int cbegin, cend, cmid; cbegin = 0; cend = matrix.size() - 1; //二分查找的end初始设置为最大的能取得值 while (cbegin < cend) { cmid = (cbegin + cend) / 2; if (val > matrix[cmid].back()) cbegin = cmid + 1; else if (val < matrix[cmid].front()) cend = cmid - 1; else break; } //定位元素可能在的行 int row = (cbegin == cend) ? cend : cmid; //利用lower_bound查找所在位置 std::vector<int>::iterator iter = lower_bound(matrix[row].begin(), matrix[row].end(), val); if (iter != matrix[row].end() && *iter == val) return make_pair(row, iter - matrix[row].begin()); else return not_found;}
- 6.1 6.2 数组、稀疏矩阵
- 稀疏数组或稀疏矩阵
- 数组(稀疏矩阵)
- 稀疏矩阵乘法(三元数组存储)
- 数据结构--数组--稀疏矩阵的建立
- 数据结构学习 第一章数组和稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构2-数组和稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 数据结构实验之数组二:稀疏矩阵
- 2017.10.30
- redis的两种持久化机制
- 关于iMX6Q QT 在UI界面显示中文的问题!
- Hexo+github构建个人博客
- 去除字符串中的空格,并将字符串翻转
- 6.1 6.2 数组、稀疏矩阵
- Android FrameWork之旅 --- Handler
- jzoj5417【NOIP2017提高A组集训10.24】方阵
- 在服务器端避免表单的重复提交 (转)
- 使用java+Mysql数据库做一个简单的登录窗口界面
- 舵机控制
- OpenGL头文件区别
- JavaScript练习
- NOI2017 部分题解