【数据结构】五、数组与广义表

目录

一、定义

二、计算数组元素地址

三、稀疏矩阵快速转置

稀疏矩阵的表示

稀疏矩阵快速转置

四、广义表


一、定义

我们所熟知的一维、二维数组的元素是原子类型。广义表中的元素除了原子类型还可以是另一个线性表。当然所有的数据元素仍然属于同一类型。

这里的数组可以是顺序结构,也可以是链式结构。

二、计算数组元素地址

公式

对于二维数组:

行优先:首地址 + [ (行标 - 行起始编号) * 列总数 + (列标 - 列起始编号) ] * 每个元素占的空间

列优先:首地址 + [ (列标 - 列起始编号) * 行总数 + (行标 - 行起始编号) ] * 每个元素占的空间

行和列标号别标反了

例一:

一个二维数组A,行下标的范围是1到6,列下标的范围是0到7,每个数组元素用相邻的6个字节存储,存储器按字节编址。那么,这个数组的体积是( )个字节

答案:288       (6-1+1)*(7-0+1)*6

例二:

设数组a[1…60, 1…70]的基地址为2048,每个元素占2个存储单元,若以列序为主序顺序存储,则元素a[32,58]的存储地址为( )

答案:8950     2048+[(58-1)*60+(32-1)]*2

 例三:

假设以行序为主序存储二维数组A=array[1..100,1..100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]=( )

答案:818

例四:

数组A[0..5,0..6]的每个元素占五个字节,将其按列优先次序存储在起始地址为1000的内存单元中,则元素A[5,5]的地址是(  )

答案:1175

例五:

假设有三维数组A(7×9×8),每个元素用相邻的6个字节存储,存储器按字节编址。已知A的起始存储位置(基地址)为1000,末尾元素A[6][8][7]的第一个字节地址为多少?

答案:4018    1000+(7×9×8-1)×6

三、稀疏矩阵快速转置

稀疏矩阵:大部分为0,非零元素较少的矩阵

稀疏矩阵的表示

1.线性表

会浪费很多空间

2.三元组表示法

第零行记录总行数,总列数和总非零元素个数;其他行按行优先记录非零元素的位置和值 

为了高效访问稀疏矩阵中任一非零元素,引入辅助向量:

num(i):记录每非0元素个数

pos(i): 记录稀疏矩阵中每行第一个非0元素在三元组中的序号

pos计算公式:

pos(1)=1

pos(i)=pos(i-1)+num(i-1)

稀疏矩阵快速转置

目的:已知原矩阵的三元组,求转置后矩阵的三元组。而且原三元组仅遍历一遍,也就是说将原三元组每条信息直接送入新三元组对应位置

所以我们需要一个指示迁移位置的数组cpos

由于转置使得每一列的第一个非零数成为每一行的第一个非零数,而三元组又是以行优先排列的,所以cpos反映了原矩阵每一列首非零元在新三元组中的编号

相当于按列遍历了原矩阵,把转置矩阵每一行的首非零元先写入新三元组对应位置

cpos计算方法cpos第一位默认为1,也就是原矩阵第一列首非零元要放在新三元组第一行。cpos后一位等于cpos前一位加前一列非零元个数(num数组负责记录每列的非零元素个数)

遍历旧三元组,cpos[列数] = 新三元组中的行号迁移一个元素后,把对应的cpos加一

由于旧矩阵从上往下从左往右遍历,所以每一列第一个拿到的元素肯定是首非零元,说明本方法合理

代码(有误):

/*快速转置的目的是通过一次遍历旧三元组,就能把原非零数的信息放到新三元组对应位置上所以我们需要一个指示迁移位置的数组cpos由于转置使得每一列的第一个非零数成为每一行的第一个非零数,而三元组又是以行优先排列的,所以cpos反映了每一列首非零元在新三元组中的编号相当于按列遍历了原矩阵,把转置矩阵每一行的首非零元安排好了计算方法:cpos第一位默认为1,也就是原矩阵第一列首非零元要放在新三元组第一行。cpos后一位等于cpos前一位加前一列非零元个数然后遍历旧三元组时,根据列数进行索引,由于旧矩阵从上往下从左往右遍历,所以每一列第一个拿到的元素肯定是首非零元迁移一个元素后,把对应的cpos加一*/
#include<stdio.h>
#include<stdlib.h>#define MAXTRIPLE 25    //三元组非零元素最大个数typedef int elemtype;typedef struct triple {int row;int col;elemtype e;
}triple;      //三元组节点,包括非零元素的行号,列号,值typedef struct {triple data[MAXTRIPLE + 1];int mrow, mcol, mnum;     //列表的总行数,总列数,非零个数,描述的是三元组。data第一行描述稀疏矩阵的行数、列数、非零数
}tsmatrix;   //三元组列表void creatematrix(elemtype* mat, int row, int col)  //创建矩阵
{printf("输入元素:");for (int i = 0; i < row; i++)for (int j = 0; j < col; j++)scanf_s("%d", &mat[(i - 1) * col + j]);
}void printmatrix(elemtype* mat, int row, int col) {for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++)printf("%d ", mat[(i - 1) * col + j]);printf("\n");}printf("\n");
}void inittriple(tsmatrix* tri, elemtype* mat, int row, int col) {   //生成三元组tri->mcol = 3;tri->mrow = 0;tri->mnum = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++)if (mat[(i - 1) * col + j] != 0) {tri->mnum++;   //新增节点,列表非零元素和行数都增加tri->mrow++;tri->data[tri->mnum].e = mat[(i - 1) * col + j];tri->data[tri->mnum].row = i;tri->data[tri->mnum].col = j;}}tri->data[0].row = row;tri->data[0].col = col;tri->data[0].e = tri->mnum;    //三元组第一行放稀疏矩阵的信息
}void printtriple(tsmatrix* tri){  //打印三元组printf("三元组矩阵为:\n");printf("行\t列\t值\n");int i;for (i = 0; i <= tri->mrow; i++) {printf("%d\t%d\t%d\n", tri->data[i].row, tri->data[i].col, tri->data[i].e);}
}void tri2mat(tsmatrix* tri) {    //将三元组还原为矩阵int i, j;elemtype* originmat = (elemtype*)malloc(sizeof(elemtype) * tri->data[0].col * tri->data[0].row);if (!originmat) return;for (i = 0; i < tri->data[0].row; i++)for (j = 0; j < tri->data[0].col; j++)originmat[i * tri->data[0].row + j] = 0;  //矩阵先全为0for (i = 1; i <= tri->mnum; i++)   //遍历三元组非零元素的信息originmat[(tri->data[i].row * tri->data[0].row) + tri->data[i].col] = tri->data[i].e;printf("矩阵为:\n");for (i = 0; i < tri->data[0].row; i++) {for (j = 0; j < tri->data[0].col; j++)printf("%d ", originmat[i * tri->data[0].row + j]);printf("\n");}
}void fasttrans(tsmatrix* tri) {     //快速转置tsmatrix* trans = (tsmatrix*)malloc(sizeof(tsmatrix));  //trans为新的三元组if (!trans) return;trans->mcol = tri->mcol;     trans->mrow = tri->mrow;trans->mnum = tri->mnum;trans->data[0].col = tri->data[0].row;trans->data[0].row = tri->data[0].col;trans->data[0].e = tri->data[0].e;     //新旧三元组关于自身的信息(行,列,非零数)相同;矩阵的行列互换,非零数相同if (tri->mnum > 0) {int i;int* num = (int*)malloc(sizeof(int) * tri->data[0].col);  //num数组用来记录矩阵每一列非零个数if (!num) return;for (i = 0; i < tri->data[0].col; i++)num[i] = 0;for (i = 1; i <= tri->mnum; i++)num[tri->data[i].col]++;int* cpos = (int*)malloc(sizeof(int) * tri->data[0].col);  //cpos用来记录计算稀疏矩阵中每列第一个非0元素在新三元组表中存放的位置if (!cpos) return;cpos[0] = 1;   //cpos首元素默认为1for (i = 1; i < tri->data[0].col; i++)cpos[i] = cpos[i - 1] + num[i - 1];   //cpos剩下元素计算方法:新cpos=旧cpos+旧num 如:第一列首非零元设为1,第二列首非零元为1跳过第一列非零元个数printf("nums:");for (i = 0; i < tri->data[0].col; i++)printf("%d ", num[i]);printf("\n");printf("cpos:");for (i = 0; i < tri->data[0].col; i++)printf("%d ", cpos[i]);printf("\n");for (i = 1; i <= tri->mnum; i++) {   //三元组数据迁移trans->data[cpos[tri->data[i].col]].row = tri->data[i].col;    //以旧三元组中列数为索引,到cpos中去查找它要去的位置,行列交换trans->data[cpos[tri->data[i].col]].col = tri->data[i].row;trans->data[cpos[tri->data[i].col]].e = tri->data[i].e;   cpos[tri->data[i].col]++;      //cpos中数据用过一次后要加一}printtriple(trans);printf("转置后的");tri2mat(trans);}elsetri2mat(tri);}int main() {int row, col;printf("输入稀疏矩阵行数:");scanf_s("%d", &row);printf("输入稀疏矩阵列数:");scanf_s("%d", &col);elemtype* mat = (elemtype*)malloc(sizeof(elemtype) * row * col);creatematrix(mat, row, col);printf("原矩阵为:\n");printmatrix (mat, row, col);tsmatrix* triple = (tsmatrix*)malloc(sizeof(tsmatrix));inittriple(triple, mat, row, col);printtriple(triple);tri2mat(triple);fasttrans(triple);
}

四、广义表

定义:广义表是线性表的推广。广义表中元素既可以是原子类型,也可以是列表

特点

1.第一个元素是表头,其余元素组成的表称为表尾

2.任何一个非空表,表头可能是原子,也可能是列表;但表尾一定是列表

3.广义表的长度 = 表中元素个数;广义表的深度 = 表中括号的最大重数

4.用小写字母表示原子类型,用大写字母表示列表。

L=( ( ) , (e) , ( a , (b , c , d) ) ),长度为3,深度为3

A=( a , (b , A) ),长度为2,深度为无穷

广义表操作

取表头:表头为单个元素,直接写出表的首位元素即可

取表尾:表尾为列表,写出除了首个元素以外的元素,外面加层括号

练习

GetTail:(b, k, p, h)                             =(k,p,h)

GetHead:( (a,b), (c,d) )                     =(a,b)

GetTail:( (a,b), (c,d) )                        =((c,d))

GetTail:( GetHead:((a,b),(c,d)) )    =(b)

GetTail: (e)       = ( )

GetHead: ( ( ) )=( )

GetTail: ( ( ) )   =( )

广义表A=(a,b,(c,d),(e,(f,g))),则Head(Tail(Head(Tail(Tail()))))值为(   )
答案:d

已知广义表A=((a,(b,c)),(a,(b,c),d)),则运算head(tail(head()))的结果是(   )

答案:(b,c)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/222127.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VSCode安装PYQT5

安装PYQT5 pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install PyQt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple 获得Python环境位置 查看函数库安装位置 pip show 函数库名 通过查询函数库&#xff0c;了解到python安装位置为 C:\User…

在 Kubernetes 上部署 Python 3.7、Chrome 和 Chromedriver(版本 114.0.5735.90)的完整指南

一、构建基础镜像 docker build -f /u01/isi/DockerFile . -t thinking_code.com/xhh/crawler_base_image:v1.0.2docker push thinking_code.com/xhh/crawler_base_image:v1.0.2 二、K8s运行Pod 三、DockerFile文件 # 基于镜像基础 FROM python:3.7# 设置代码文件夹工作目录…

泛微e-cology XmlRpcServlet文件读取漏洞复现

漏洞介绍 泛微新一代移动办公平台e-cology不仅组织提供了一体化的协同工作平台,将组织事务逐渐实现全程电子化,改变传统纸质文件、实体签章的方式。泛微OA E-Cology 平台XmRpcServlet接口处存在任意文件读取漏洞&#xff0c;攻击者可通过该漏洞读取系统重要文件 (如数据库配置…

python编程(1)之通用引脚GPIO使用

在之前的章节中&#xff0c;小编带领大家学习了&#xff1a;如何构建esp32的python开发环境-CSDN博客 今天小编带领大家开始学习python编程的第一节&#xff0c;通用引脚。esp32c3核心板是一个高度集成&#xff0c;功能丰富的模块&#xff0c;来看下他的功能分布&#xff1a; 我…

【小黑嵌入式系统第十一课】μC/OS-III程序设计基础(一)——任务设计、任务管理(创建基本状态内部任务)、任务调度、系统函数

上一课&#xff1a; 【小黑嵌入式系统第十课】μC/OS-III概况——实时操作系统的特点、基本概念&#xff08;内核&任务&中断&#xff09;、与硬件的关系&实现 文章目录 一、任务设计1.1 任务概述1.2 任务的类型1.2.1 单次执行类任务&#xff08;运行至完成型&#…

centos7安装开源日志系统graylog5.1.2

安装包链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Zl5s7x1zMWpuKfaePy0gPg?pwd1eup 提取码&#xff1a;1eup 这里采用的shell脚本安装&#xff0c;脚本如下&#xff1a; 先使用命令产生2个参数代入到脚本中&#xff1a; 使用pwgen生成password_secret密码 …

Linux之进程(五)(进程控制)

目录 一、进程创建 1、fork函数创建进程 2、fork函数的返回值 3、fork常规用法 4、fork调用失败的原因 二、进程终止 1、进程终止的方式 2、进程退出码 3、进程的退出方法 三、进程等待 1、进程等待的必要性 2、wait函数 3、waitpid函数 四、进程程序替换 1、概念…

利用ffmpeg cv2取h265码流视频(转换图片灰屏问题解决)

利用海康威视相机拍出来的视频是H265格式的&#xff0c;相比于常规的H264编码&#xff0c;压缩率更高&#xff0c;但因此如果直接用正常取流方法读取&#xff0c;会出现无法读取的情况 1. 如图h265码流取出图片为灰屏 2 、解决灰屏问题 import subprocess import cv2# 将h265流…

100GPTS计划-AI学术AcademicRefiner

地址 https://chat.openai.com/g/g-LcMl7q6rk-academic-refiner https://poe.com/AcademicRefiner 测试 减少相似性 增加独特性 修改http://t.csdnimg.cn/jyHwo这篇文章微调 专注于人工智能、科技、金融和医学领域的学术论文改写&#xff0c;秉承严格的专业和学术标准。 …

使用opencv实现图像中几何图形检测

1 几何图形检测介绍 1.1 轮廓(contours) 什么是轮廓&#xff0c;简单说轮廓就是一些列点相连组成形状、它们拥有同样的颜色、轮廓发现在图像的对象分析、对象检测等方面是非常有用的工具&#xff0c;在OpenCV 中使用轮廓发现相关函数时候要求输入图像是二值图像&#xff0c;这…

华为安防监控摄像头

华为政企42 华为政企 目录 上一篇华为政企城市一张网研究报告下一篇华为全屋wifi6蜂鸟套装标准

【数据结构】二叉树的模拟实现

前言:前面我们学习了堆的模拟实现&#xff0c;今天我们来进一步学习二叉树&#xff0c;当然了内容肯定是越来越难的&#xff0c;各位我们一起努力&#xff01; &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:数据结构 &#x1f448; &…

大创项目推荐 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

LabVIEW开发自动驾驶的双目测距系统

LabVIEW开发自动驾驶的双目测距系统 随着车辆驾驶技术的不断发展&#xff0c;自动驾驶技术正日益成为现实。从L2级别的辅助驾驶技术到L3级别的受条件约束的自动驾驶技术&#xff0c;车辆安全性和智能化水平正在不断提升。在这个过程中&#xff0c;车辆主动安全预警系统发挥着关…

CloudCanal x Debezium 打造实时数据流动新范式

简述 Debezium 是一个开源的数据订阅工具&#xff0c;主要功能为捕获数据库变更事件发送到 Kafka。 CloudCanal 近期实现了从 Kafka 消费 Debezium 格式数据&#xff0c;将其 同步到 StarRocks、Doris、Elasticsearch、MongoDB、ClickHouse 等 12 种数据库和数仓&#xff0c;…

simulink代码生成(一)——环境搭建

一、安装C2000的嵌入式环境&#xff1b; 点击matlab附加功能&#xff0c; 然后搜索C2000&#xff0c;安装嵌入式硬件支持包&#xff1b;点击安装即可&#xff1b;&#xff08;目前还不知道破解版的怎么操作&#xff0c;目前我用的是正版的这样&#xff0c;完全破解的可能操作…

华为数通方向HCIP-DataCom H12-831题库(多选题:201-220)

第201题 在多集群RR组网中,每个集群中部署了一台RR设备及其客户机,各集群的RR与为非客户机关系,并建立IBGP全连接。以下关于BGP路由反射器发布路由规则的描述,正确的有哪些? A、若某RR从EBGP对等体学到的路由,此RR会传递给其他集群的RR B、若某RR从非客户机IBGP对等体学…

Axure之中继器的使用(交互动作reperter属性Item属性)

目录 一.中继器的基本使用 二.中继器的动作&#xff08;增删改查&#xff09; 2.1 新增 2.2 删除 2.3 更新行 2.4 效果展示 2.5 模糊查询 三.reperter属性 在Axure中&#xff0c;中继器&#xff08;Repeater&#xff09;是一种功能强大的组件&#xff0c;用于创建重复…

C# 使用MSTest进行单元测试

目录 写在前面 代码实现 执行结果 写在前面 MSTest是微软官方提供的.NET平台下的单元测试框架&#xff1b;可使用DataRow属性来指定数据&#xff0c;驱动测试用例所用到的值&#xff0c;连续对每个数据化进行运行测试&#xff0c;也可以使用DynamicData 属性来指定数据&…

Flink系列之:Savepoints

Flink系列之&#xff1a;Savepoints 一、Savepoints二、分配算子ID三、Savepoint 状态四、算子五、触发Savepoint六、Savepoint 格式七、触发 Savepoint八、使用 YARN 触发 Savepoint九、使用 Savepoint 停止作业十、从 Savepoint 恢复十一、跳过无法映射的状态恢复十二、Resto…