@value 数组_数据结构与算法:12 数组与稀疏矩阵
12 数组与稀疏矩阵
知识结构:
1. 数组
1.1 数组的定义
数组是具有一定顺序关系的若干对象组成的集合,组成数组的对象称为数组元素。
例如:
- 向量对应一维数组
- 矩阵对应二维数组
数组名表示群体的共性,即具有同一种数据类型;
下标表示个体的个性,即各自占有独立的单元。
1.2 数组的存储
(1)维数组的定义
下标由个数组成的数组称为维数组。
例如:
//一维数组(线)int[] a = new int[10];
//二维数组 (面)int[ , ] a = new int[2,3];
//三维数组 (体),类比:书(体)【2.页码 3.行 4.列】 int[ , , ] a = new int[2,3,4];
(2)数组存储的特点
- 数组元素在内存中按顺序连续存储。
- 数组的存储分配按照行(C、C++、C#等)或列(Forturn等)进行。
- 数组名表示该数组的首地址,是常量。
(3)常用数组的存储
一维数组a[n]
各元素按下角标依次存放。
例:int[] a = new int[5];
二维数组a[m,n]
例:int[ , ] a = new int[2,3];
三维数组a[m,n,l]
第一维下标变化最慢,第三维(最后一维)下标变化最快。
例:int[ , , ] a = new int[2,3,4];
注意:
C#中int[,]
与int[][]
定义数组的区别
int[,]
行数,列数确定
static void Main(string[] args){
int[,] Arr = new int[2, 5] { { 1, 2, 3, 5, 6 }, { 1, 2, 3, 4, 5 } };
for (int i = 0; i < 2; ++i) {for (int j = 0; j < 5; ++j) { Console.Write(Convert.ToString(Arr[i, j]) + " "); } Console.WriteLine(); }// 1 2 3 5 6// 1 2 3 4 5}
int[][]
行数确定,列数不定
static void Main(string[] args){
int[][] Arr = new int[3][]; //表示含有三个一维数组的数组 Arr[0] = new int[5] { 1, 2, 3, 4, 5 }; Arr[1] = new int[2] { 0, 1 }; Arr[2] = new int[0] { };
for (int i = 0; i < Arr.Length; ++i) { foreach (int j in Arr[i]) { Console.Write(j + " "); } Console.WriteLine(); }// 1 2 3 4 5// 0 1// }
1.3 数组的分类
数组可分为静态数组和动态数组两类。
(1)静态数组
在程序编译时分配空间的数组。
例:
//静态数组(声明之后数组长度不可改变)int[] a = new int[10];
(2)动态数组
在程序运行时分配空间的数组(声明之后数组长度可根据问题而调整)。
using System;
namespace LinearStruct{/// /// 动态数组的抽象数据类型实现/// /// 动态数组中元素的类型public class DArraywhere T : IComparable {private T[] _array;/// /// 获取动态数组的当前长度/// public int Size { get; private set; }/// /// 初始化DArray类的新实例/// /// 动态数组的初始长度public DArray(int size){if (size <= 0)throw new ArgumentOutOfRangeException(); Size = size; _array = new T[Size]; }/// /// 改变动态数组的长度/// /// 动态数组的新长度public void ReSize(int newSize){if (newSize <= 0)throw new ArgumentOutOfRangeException();if (Size != newSize) { T[] newArray = new T[newSize];int n = newSize < Size ? newSize : Size;for (int i = 0; i < n; i++) { newArray[i] = _array[i]; } _array = newArray; Size = newSize; } }/// /// 获取或设置指定索引处的元素/// /// 要获得或设置的元素从零开始的索引/// 指定索引处的元素public T this[int index] { get {if (index < 0 || index > Size - 1)throw new IndexOutOfRangeException();return _array[index]; }set {if (index < 0 || index > Size - 1)throw new IndexOutOfRangeException(); _array[index] = value; } } }}
1.4 动态数组的应用
编写一段代码,要求输入一个整数N
,用动态数组A
来存放2~N
之间所有5或7的倍数,输出该数组。
例如:N=100
则输出:5 7 10 14 15 20 21 25 28 30 35 40 42 45 49 50 55 56 60 63 65 70 75 77 80 84 85 90 91 95 98 100
参考界面如下:
static void Main(string[] args){ Console.WriteLine("N=");string s = Console.ReadLine();int n;if (int.TryParse(s, out n)) { DArray<int> arr = new DArray<int>(10);int j = 0;for (int i = 2; i <= n; i++) {if (i % 5 == 0 || i % 7 == 0) {if (j == arr.Size) arr.ReSize(arr.Size + 10);
arr[j] = i; j++; } }for (int i = 0; i < j; i++) { Console.Write(arr[i] + " "); } }}
2. 稀疏矩阵
2.1 稀疏矩阵的定义与操作
(1)稀疏矩阵的定义
若矩阵中非零元素的个数远远小于零元素的个数,则称为稀疏矩阵。
例:
若用二维数组存储,则太浪费存储空间。
(2)稀疏矩阵的操作
- 获取矩阵的行数
- 获取矩阵的列数
- 获取或设置指定索引处的元素
- 矩阵加法
- 矩阵转置
- 矩阵乘法
namespace LinearStruct{/// /// 矩阵的抽象数据类型/// public interface IMatrix {/// /// 获取矩阵的行数/// int Rows { get; }/// /// 获取矩阵的列数/// int Cols { get; }/// /// 获取或设置指定索引处的元素/// /// 要获取或设置的元素从零开始的行索引/// 要获取或设置的元素从零开始的列索引/// T this[int i, int j] { get; set; }/// /// 矩阵加法/// /// 与之相加的另一个矩阵/// 相加后的新矩阵 IMatrix Add(IMatrix b);/// /// 矩阵转置/// /// 转置后的新矩阵 IMatrix Transpose();/// /// 矩阵乘法/// /// 与之右乘的另一个矩阵/// 相乘后的新矩阵 IMatrix Multiply(IMatrix b); }}
2.2 稀疏矩阵的存储与实现
可以利用(Row,Col,Value)
的方式存储和定位稀疏矩阵中的非零元素,这种存储稀疏矩阵结点的方式称为三元组(Triple)。
利用顺序的方式进行存储:
利用链式的方式进行存储:
(1)对结点的封装
using System;
namespace LinearStruct{/// /// 稀疏矩阵结点/// public class Triple : IComparable {/// /// 获取结点所在矩阵中的行索引/// public int Row { get; }/// /// 获取结点所在矩阵中的列索引/// public int Col { get; }/// /// 获取或设置结点在矩阵中的值/// public double Value { get; set; }/// /// 初始化Triple类的新实例/// /// 结点所在矩阵中的行索引/// 结点所在矩阵中的列索引/// 结点在矩阵中的值public Triple(int i, int j, double value){if (i < 0 || j < 0)throw new Exception("数组元素位置无效."); Row = i; Col = j; Value = value; }/// /// Triple类的输出字符串/// /// Triple类的输出字符串public override string ToString(){return string.Format("({0},{1},{2})", Row, Col, Value); }/// /// 比较三元组中数据的大小/// /// 被比较的三元组/// public int CompareTo(Triple other){if (Value < other.Value) return -1;if (Value > other.Value) return 1;return 0; } }}
(2)对稀疏矩阵的封装
using System;
namespace LinearStruct{/// /// 矩阵抽象数据类型的实现--稀疏矩阵/// public class SparseMatrix : IMatrix<double> {private readonly DLinkList _lst;/// /// 获取稀疏矩阵的行数/// public int Rows { get; }/// /// 获取稀疏矩阵的列数/// public int Cols { get; }/// /// 初始化SparseMatrix类的新实例/// /// 稀疏矩阵的行数/// 稀疏矩阵的列数public SparseMatrix(int rows, int cols){if (rows <= 0 || cols <= 0)throw new ArgumentOutOfRangeException(); Rows = rows; Cols = cols; _lst = new DLinkList(); }private DNode GetIndex(int i, int j) { DNode temp = _lst.PHead;while (temp != null) {if (temp.Data.Row == i && temp.Data.Col == j)break; temp = temp.Next; }return temp; }private void RemoveNode(DNode node){if (node.Next == null) { _lst.Remove(_lst.Length - 1); }else if (node.Prior == null) { _lst.Remove(0); }else { node.Prior.Next = node.Next; node.Next.Prior = node.Prior; } }/// /// 获取或设置指定索引处的元素/// /// 要获取或设置的元素从零开始的行索引/// 要获取或设置的元素从零开始的列索引/// public double this[int i, int j] { get {if (i < 0 || i > Rows - 1 || j < 0 || j > Cols - 1)throw new IndexOutOfRangeException(); DNode node = GetIndex(i, j);return node == null ? 0.0 : node.Data.Value; }set {if (i < 0 || i > Rows - 1 || j < 0 || j > Cols - 1)throw new IndexOutOfRangeException(); DNode node = GetIndex(i, j);if (node == null) {if (value != 0.0) { _lst.InsertAtRear(new Triple(i, j, value)); } }else {if (value != 0.0) { node.Data.Value = value; }else { RemoveNode(node); } } } }/// /// 矩阵加法/// /// 与之相加的另一个矩阵/// 相加后的新矩阵public SparseMatrix Add(SparseMatrix b){if (b == null)throw new ArgumentNullException();if (b.Rows != Rows || b.Cols != Cols)throw new Exception("两矩阵不能相加."); SparseMatrix temp = new SparseMatrix(Rows, Cols);for (int i = 0; i < Rows; i++)for (int j = 0; j < Cols; j++) temp[i, j] = this[i, j] + b[i, j];return temp; }/// /// 矩阵转置/// /// 转置后的新矩阵public SparseMatrix Transpose(){ SparseMatrix temp = new SparseMatrix(Cols, Rows);for (int i = 0; i < temp.Rows; i++)for (int j = 0; j < temp.Cols; j++) temp[i, j] = this[j, i];return temp; }/// /// 矩阵乘法/// /// 与之右乘的另一个矩阵/// 相乘后的新矩阵public SparseMatrix Multiply(SparseMatrix b){if (b == null)throw new ArgumentNullException();if (Cols != b.Rows)throw new Exception("两矩阵不能相乘."); SparseMatrix temp = new SparseMatrix(Rows, b.Cols);for (int i = 0; i < Rows; i++) {for (int j = 0; j < b.Cols; j++) {double value = 0.0;for (int k = 0; k < Cols; k++) value += this[i, k] * b[k, j]; temp[i, j] = value; } }return temp; }/// /// 矩阵加法运算/// /// 第一个矩阵/// 第二个矩阵/// 相加后的新矩阵public static SparseMatrix operator +(SparseMatrix a, SparseMatrix b) {if (a == null || b == null)throw new ArgumentNullException();return a.Add(b); }/// /// 矩阵乘法运算/// /// 左边的矩阵/// 右边的矩阵/// 相乘后的新矩阵public static SparseMatrix operator *(SparseMatrix a, SparseMatrix b) {if (a == null || b == null)throw new ArgumentNullException();return a.Multiply(b); }/// /// SparseMatrix类的输出字符串/// /// SparseMatrix类的输出字符串public override string ToString(){string str = string.Empty; DNode temp = _lst.PHead;while (temp != null) { str += temp.Data + "\n"; temp = temp.Next; }return str; } IMatrix<double> IMatrix<double>.Add(IMatrix<double> b) {return Add((SparseMatrix)b); } IMatrix<double> IMatrix<double>.Transpose() {return Transpose(); } IMatrix<double> IMatrix<double>.Multiply(IMatrix<double> b) {return Multiply((SparseMatrix)b); } }}
举例:
static void Main(string[] args){ IMatrix<double> a = new SparseMatrix(2, 3); IMatrix<double> b = new SparseMatrix(3, 2); SparseMatrix c = new SparseMatrix(2, 2); a[0, 2] = 1; a[1, 0] = 1; b[1, 1] = 4; b[2, 0] = 1; c[0, 1] = 1; c[1, 0] = 1; SparseMatrix d = (SparseMatrix)a * (SparseMatrix)b + c; IMatrix<double> e = a.Multiply(b).Add(c); Console.WriteLine("D:\n{0}", d); Console.WriteLine("E:\n{0}", e);
// D:// (0, 0, 1)// (0, 1, 1)// (1, 0, 1)// E:// (0, 0, 1)// (0, 1, 1)// (1, 0, 1)}
@value 数组_数据结构与算法:12 数组与稀疏矩阵相关推荐
- arrays中copyof复制两个数组_数据结构与算法(3)数组
前言 数组(Array)是一种线性表数据结构,利用一组连续的内存空间,存储一组具有相同类型的数据. 概念介绍 首先我们说一下什么是线性表,线性表就是数据排成一条线的数据结构,每个线性表最多只有前和后两 ...
- JavaScript数据结构和算法简述——数组
为什么先讲数组 数据结构可以简单的被分为线性结构和非线性结构. 线性结构大致包括: 数组(连续存储): 链表(离散存储): 栈(线性结构常见应用,由链表或数组增删和改进功能实现): 队列(线性结构常见 ...
- 数据结构与算法---稀疏数组
数据结构与算法-稀疏数组 1.基本介绍: 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 2.稀疏数组的处理方法是: (1)记录数组一共有几行几列,有多少个 ...
- 数组【数据结构与算法Java】
数组[数据结构与算法Java] 数组 数组 略
- mooc数据结构与算法python版期末测验_中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案...
中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案 更多相关问题 采用fopen()函数打开文件,支持文件读取的参数有: [简答题]简单阐述高分子材料热-机械特征及成型加工的关系,并 ...
- 嵌入式团队培训_数据结构和算法概述
嵌入式团队培训_数据结构与算法概述 要求:理解并记忆即可,会求解算法的时间复杂度 一:数据结构 1.逻辑结构: 2.物理结构 3.抽象数据类型 二:算法 1.算法的五个基本特征: 2.算法设计的要求 ...
- 怎样将树的中序遍历的数输入到一个数组中_数据结构与算法-二叉查找树平衡(DSW)...
上一节探讨了二叉查找树的基本操作,二叉查找树的查找效率在理想状态下是O(lgn),使用该树进行查找总是比链表快得多.但是,该论点并不总是正确,因为查找效率和二叉树的形状息息相关.就像这样: 图1-1给 ...
- 尚硅谷01 数据结构与算法_数据结构与算法介绍+稀疏数组
数据结构与算法的关系 几个实际编程中遇到的问题 要想写出优秀的算法,首先应该能读懂别人写好的算法. 将生活中遇到的实际问题,使用程序来解决 线性结构和非线性结构 线性结构和非线性结构的关系: 数据结构 ...
- 数据结构与算法--有序数组中找出和为s的两个数字
有序数组中找和为s的两个数字 题目:输入一个递增排序的数组array, 和一个数字s, 在数组中找出两个数,使得这两个数的和是s,如果有多对,输出一对即可. 最简单方案 双循环,每次获取一个数据,和数 ...
最新文章
- JavaI/O:使用InputStreamReader和BufferedReade实现控制器输入输出
- SpringFlux入门(上篇)
- 使用celery的backend异步获取结果
- 安装XCode7.1后,QT5.5出现的各种问题解决方案
- 交际中你所不知道的说话的12个技巧!
- Hibernate陷阱
- RMAN 还原与恢复
- Silverlight实用窍门系列:28.Silverlight制作随机分布雷达扫描点,模拟雷达扫描图之被扫描设备【附带源码实例】...
- Selenium之前世今生
- JavaScript document对象
- 网管服务器系统巡检报告,网络设备巡检报告-20210730125215.docx-原创力文档
- 信数金服:物联网案例之物联网系统如何进行实时决策
- stm32-mini-LCD液晶显示实验
- 大量查询中通快运在途信息,并分析中转延误
- 编译安装Memcached
- 浅谈产业界与学术界的合作研究(转)
- 遗传算法(Genetic Algorithm,GA)实现数据排序,python
- web前端图片极限优化策略
- Maths | Metropolis-Hastings algorithm
- Python 学习知识点梳理