12 数组与稀疏矩阵

知识结构:

图1 知识结构

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];

图2 一维数组存储

二维数组a[m,n]

例:int[ , ] a = new int[2,3];

图3 二维数组存储

三维数组a[m,n,l]

第一维下标变化最慢,第三维(最后一维)下标变化最快。

例:int[ , , ] a = new int[2,3,4];

图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)动态数组

在程序运行时分配空间的数组(声明之后数组长度可根据问题而调整)。

图5 动态数组类图
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

参考界面如下:

图6 动态数组实验界面
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)稀疏矩阵的操作

  • 获取矩阵的行数
  • 获取矩阵的列数
  • 获取或设置指定索引处的元素
  • 矩阵加法
  • 矩阵转置
  • 矩阵乘法

图7 矩阵接口
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)。

图8 稀疏矩阵结点的存储

利用顺序的方式进行存储:

图9 顺序方式存储稀疏矩阵

利用链式的方式进行存储:

图10 链式方式存储稀疏矩阵

(1)对结点的封装

图11 稀疏矩阵结点类图
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)对稀疏矩阵的封装

图12 稀疏矩阵类图
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 数组与稀疏矩阵相关推荐

  1. arrays中copyof复制两个数组_数据结构与算法(3)数组

    前言 数组(Array)是一种线性表数据结构,利用一组连续的内存空间,存储一组具有相同类型的数据. 概念介绍 首先我们说一下什么是线性表,线性表就是数据排成一条线的数据结构,每个线性表最多只有前和后两 ...

  2. JavaScript数据结构和算法简述——数组

    为什么先讲数组 数据结构可以简单的被分为线性结构和非线性结构. 线性结构大致包括: 数组(连续存储): 链表(离散存储): 栈(线性结构常见应用,由链表或数组增删和改进功能实现): 队列(线性结构常见 ...

  3. 数据结构与算法---稀疏数组

    数据结构与算法-稀疏数组 1.基本介绍: ​ 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 2.稀疏数组的处理方法是: ​ (1)记录数组一共有几行几列,有多少个 ...

  4. 数组【数据结构与算法Java】

    数组[数据结构与算法Java] 数组 数组 略

  5. mooc数据结构与算法python版期末测验_中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案...

    中国大学MOOC(慕课)_数据结构与算法Python版_测试题及答案 更多相关问题 采用fopen()函数打开文件,支持文件读取的参数有: [简答题]简单阐述高分子材料热-机械特征及成型加工的关系,并 ...

  6. 嵌入式团队培训_数据结构和算法概述

    嵌入式团队培训_数据结构与算法概述 要求:理解并记忆即可,会求解算法的时间复杂度 一:数据结构 1.逻辑结构: 2.物理结构 3.抽象数据类型 二:算法 1.算法的五个基本特征: 2.算法设计的要求 ...

  7. 怎样将树的中序遍历的数输入到一个数组中_数据结构与算法-二叉查找树平衡(DSW)...

    上一节探讨了二叉查找树的基本操作,二叉查找树的查找效率在理想状态下是O(lgn),使用该树进行查找总是比链表快得多.但是,该论点并不总是正确,因为查找效率和二叉树的形状息息相关.就像这样: 图1-1给 ...

  8. 尚硅谷01 数据结构与算法_数据结构与算法介绍+稀疏数组

    数据结构与算法的关系 几个实际编程中遇到的问题 要想写出优秀的算法,首先应该能读懂别人写好的算法. 将生活中遇到的实际问题,使用程序来解决 线性结构和非线性结构 线性结构和非线性结构的关系: 数据结构 ...

  9. 数据结构与算法--有序数组中找出和为s的两个数字

    有序数组中找和为s的两个数字 题目:输入一个递增排序的数组array, 和一个数字s, 在数组中找出两个数,使得这两个数的和是s,如果有多对,输出一对即可. 最简单方案 双循环,每次获取一个数据,和数 ...

最新文章

  1. JavaI/O:使用InputStreamReader和BufferedReade实现控制器输入输出
  2. SpringFlux入门(上篇)
  3. 使用celery的backend异步获取结果
  4. 安装XCode7.1后,QT5.5出现的各种问题解决方案
  5. 交际中你所不知道的说话的12个技巧!
  6. Hibernate陷阱
  7. RMAN 还原与恢复
  8. Silverlight实用窍门系列:28.Silverlight制作随机分布雷达扫描点,模拟雷达扫描图之被扫描设备【附带源码实例】...
  9. Selenium之前世今生
  10. JavaScript document对象
  11. 网管服务器系统巡检报告,网络设备巡检报告-20210730125215.docx-原创力文档
  12. 信数金服:物联网案例之物联网系统如何进行实时决策
  13. stm32-mini-LCD液晶显示实验
  14. 大量查询中通快运在途信息,并分析中转延误
  15. 编译安装Memcached
  16. 浅谈产业界与学术界的合作研究(转)
  17. 遗传算法(Genetic Algorithm,GA)实现数据排序,python
  18. web前端图片极限优化策略
  19. Maths | Metropolis-Hastings algorithm
  20. Python 学习知识点梳理

热门文章

  1. 做好项目,从正确定义问题开始!
  2. 与WebXR共同创建者Diego Marcos一起探讨沉浸式Web的未来(下)
  3. 音视频技术开发周刊 | 196
  4. 实时音视频助力在线教育风口
  5. LiveVideoStack线上分享第四季(八):实时远程医学影像服务质量保障与网络优化...
  6. ffplay.c学习-5-视频输出和尺⼨变换
  7. LeetCode——排序
  8. 斩获2019 Thales AIChallenge4Health第一,腾讯优图医疗AI再获突破
  9. mysql面试精选【推荐】
  10. Hadoop 04_Hadoop2.0