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

目录

一、定义

二、计算数组元素地址

三、稀疏矩阵快速转置

稀疏矩阵的表示

稀疏矩阵快速转置

四、广义表


一、定义

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

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

二、计算数组元素地址

公式

对于二维数组:

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

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

行和列标号别标反了

例一:

一个二维数组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;  //矩阵先全为0

	for (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首元素默认为1
		for (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);
	}
	else
		tri2mat(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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深圳市城市更新区域关注程度分析数据,tiff格式,附数据可视化,精细到区县

基本信息. 数据名称: 深圳市城市更新区域关注程度分析数据 数据格式: tiff 时间版本&#xff1a;2022年 数据几何类型: 无 数据精度&#xff1a;区县 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据 数据可视化. www.bajidata.com

微信小程序-textarea组件字数实时更新

一、前言 本文实现的是在小程序中&#xff0c;textarea文本框输入文字后&#xff0c;实时显示文字的字数&#xff0c;获取更好的用户输入体验以及提示。 下图是实现的效果 二、代码实现 2-1、wxml代码 <view style"padding: 30rpx;"><view style"…

【已解决】解决Springboot项目访问本地图片等静态资源无法访问的问题

今天在开发一个招聘系统的时候&#xff0c;有投递简历功能&#xff0c;有投递就会有随之而来的查看简历对吧&#xff0c;我投递过的简历&#xff0c;另存为一个文件夹&#xff0c;就是说本地磁盘(或者服务器)有一个专门存放投递过的简历的文件夹&#xff0c;用于存放PDF&#x…

Java最全面试题专题---5、Spring面试题(1)

Spring概述&#xff08;10&#xff09; 什么是spring? Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack&#xff08;一站式&#xff…

【jvm从入门到实战】(十) 实战篇-内存调优

内存溢出和内存泄漏&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内存泄漏。内存泄漏绝大多数情况都是由堆内存泄漏引起的。少量的内存泄漏可以容忍&#x…

基于Linphone android sdk开发Android软话机

1.Linphone简介 1.1 简介 LinPhone是一个遵循GPL协议的开源网络电话或者IP语音电话&#xff08;VOIP&#xff09;系统&#xff0c;其主要如下。使用linphone&#xff0c;开发者可以在互联网上随意的通信&#xff0c;包括语音、视频、即时文本消息。linphone使用SIP协议&#…

云原生系列3-Kubernetes

1、Kubernetes概述 k8s缩写是因为k和s之间有八个字符。k8s是基于容器技术的分布式架构方案。官网&#xff1a;https://kubernetes.io/zh-cn/ Google在 2014年开源了Kubernetes项目&#xff0c;Kubernetes是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。同样类似的…

拥抱鸿蒙 - 在展讯T606平台上的探索与实践

前 言 自OpenHarmony 问世后受到了社会各界的广泛关注&#xff0c;OpenHarmony 的生态系统在如火如荼的发展。 酷派作为一家积极拥抱变化的公司&#xff0c;经过一段时间的探索与实践&#xff0c;成功实现将OpenHarmony 系统接入到展讯平台上&#xff0c;我们相信这是一个重要…

华为麒麟系统与鸿蒙系统:发展历程、问题解决与未来展望

导言 华为作为全球领先的科技企业&#xff0c;其自主研发的麒麟系统和鸿蒙系统备受瞩目。本文将深入研究这两者的发展历程、遇到的问题、解决过程&#xff0c;探讨未来的可用范围以及在全球的应用和研究趋势&#xff0c;进一步探讨在哪些方面能取胜&#xff0c;并在哪些领域发力…

芯知识 | WT2003HP8-32N语音芯片采用QFN32形式小体积封装的应用优势介绍

唯创知音WT2003HP8-32N高品质MP3音频语音芯片&#xff0c;以其QFN32&#xff08;44毫米&#xff09;封装的应用优势&#xff0c;在音频处理领域独树一帜。这款芯片不仅体积小巧&#xff0c;而且功能强大&#xff0c;适用于多种应用场景。 一、高品质音频处理 唯创知音WT2003HP…

阿里云ECS配置IPv6后,如果无法访问该服务器上的网站,可检查如下配置

1、域名解析到这个IPv6地址,同一个子域名可以同时解析到IPv4和IPv6两个地址&#xff0c;这样就可以给网站配置ip4和ipv6双栈&#xff1b; 2、在安全组规则开通端口可访问&#xff0c;设定端口后注意授权对象要特殊设置“源:::/0” 3、到服务器nginx配置处&#xff0c;增加端口…

pip 常用指令 pip download 命令用法介绍

pip download 是一个用于从Python包索引(PyPI)下载Python包的命令行工具。它可以下载特定版本的包&#xff0c;或者下载满足特定条件的所有包。 命令 pip download 的参数包括 -d 或 --dest&#xff1a;指定下载文件的保存路径。-r 或 --requirement&#xff1a;从一个需求文…

百度侯震宇详解:大模型将如何重构云计算?

12月20日&#xff0c;在2023百度云智大会智算大会上&#xff0c;百度集团副总裁侯震宇以“大模型重构云计算”为主题发表演讲。他强调&#xff0c;AI原生时代&#xff0c;面向大模型的基础设施体系需要全面重构&#xff0c;为构建繁荣的AI原生生态筑牢底座。 侯震宇表示&…

Java|IDEA 中添加编译参数 --add-exports

方法1 File > Settings > Build, Execution, Deployment > Compiler > Java Compiler > Javac Options > Override compiler parameters per-module 点击&#xff1a; 点击OK 双击Compliation options&#xff0c;输入后回车&#xff1a; 方法2 找到出错…

快速搭建Grafana Promethus 服务器监控系统

该文参考文章&#xff0c;其中又遇到一些问题&#xff0c;并解决&#xff0c;当前主要为了记录一下 探针 Grafana Prometheus 之比 Docker 更简单的部署流程 - 承飞之咎本文重在 Grafana Prometheus 探针 方案的部署流程&#xff0c;介绍和更多使用请到&#xff1a;探针 ̵……

【Vulnhub 靶场】【DarkHole: 1】【简单】【20210730】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/darkhole-1,724/ 靶场下载&#xff1a;https://download.vulnhub.com/darkhole/DarkHole.zip 靶场难度&#xff1a;简单 发布日期&#xff1a;2021年07月18日 文件大小&#xff1a;2.9 GB 靶场作者&#xff1a…

JavaWeb笔记之WEB开发

一、引言 1.1 C/S和B/S C/S和B/S是软件发展过程中出现的两种软件架构方式。 1.2 C/S架构 &#xff08;Client/Server 客户端/服务器&#xff09;。 特点&#xff1a;必须在客户端安装特定软件。 优点&#xff1a;图形效果显示较好(如&#xff1a;3D游戏)。 缺点&#xff1…

简单配置keil并与vscode关联使用

高端的食材往往采用最粗暴的烹饪方式&#xff0c;主打的就是xx 最终实现的是keil与vscode联调C51开发 1.vscode用于写代码可以用它的补全功能还有索引功能等非常适合&#xff0c;还有部分语法检查等&#xff1b; 2.keil就用来良好调试与编译功能&#xff1b; 全部安装最新版…

企业直聘招聘人才求职系统招聘会小程序系统源码

技术栈&#xff1a; 端 原生小程序开发 后端php7.2 数据库mysql5.6 主要功能&#xff1a; 企业入住 ,企业直聘 个人实名认证&#xff0c;人才求职 发布线上招聘会 企业招聘邀请 个人简历置顶 刷新 浏览足迹浏览 附近 招聘信息查看

Polygon zkEVM Spearbit审计报告解读(2022年12月版本)

1. 引言 前序博客&#xff1a; Polygon zkEVM Hexens审计报告解读&#xff08;2022年12月至2023年2月版本&#xff09; 主要见&#xff1a; Polygon zkEVM Security Review: December 2022 Engagement Polygon zkEVM为提供&#xff08;opcode层面兼容的&#xff09;EVM等价…