数据结构-数组(稀疏矩阵转置)和广义表

目录

  • 1、数组
      • 定义
    • 1)数组存储地址计算
      • 示例
        • ①行优先
        • ②列优先
    • 2)稀疏矩阵的转置
      • 三元组顺序表
        • 结构定义
      • ①普通矩阵转置
      • ②三元组顺序表转置稀疏矩阵
      • ③稀疏矩阵的快速转置
    • 3)十字链表
      • 结构定义
  • 2、广义表
      • 定义
    • 1)基本操作
      • ①GetHead
      • ②GetTail
    • 2)构造存储结构的两种方法
      • 表头表尾
        • 结构定义
    • 3)递归算法
      • ①求广义表深度
      • ②复制广义表
      • ③创建广义表

1、数组

定义

数组是一种用于存储多个相同类型数据的集合,其元素在内存中连续存放并按照一定的顺序排列。这种有序性和连续性使得数组在访问时具有较高的效率。数组的特点包括所有元素具有相同的数据类型、可以通过索引快速访问任意元素、支持各种操作如遍历和排序等,并且数组的定义和初始化方式在不同编程语言中有所不同。

1)数组存储地址计算

数组存储地址的计算主要依赖于数组的起始地址、元素的数据类型(即每个元素所占的字节数)以及元素的下标位置

一维数组的存储地址计算

首元素地址:假设一维数组A的首地址为L,且每个元素占用C个字节。则数组中任意元素A[i]的地址可以通过公式Loc(A[i]) = L + i * C来计算。
示例:如果数组A的首地址是1000,每个元素占4个字节,那么A[3]的地址就是1000 + 3 * 4 = 1012。

二维数组的存储地址计算

行优先存储:在行优先存储中,二维数组的元素按照行的顺序依次存储。对于二维数组B[m][n],元素B[i][j]的地址计算公式为Loc(B[i][j]) = Loc(B[0][0]) + (i * n + j) * C,其中C是每个元素占用的字节数。
列优先存储:在列优先存储中,二维数组的元素按照列的顺序依次存储。对于二维数组B[m][n],元素B[i][j]的地址计算公式为Loc(B[i][j]) = Loc(B[0][0]) + (j * m + i) * C。
示例:假设有一个3x4的二维数组B,按行优先存储,首地址为1000,每个元素占2个字节。那么B[2][3]的地址就是1000 + (2*4 + 3) * 2 = 1026。

多维数组的存储地址计算

对于更高维度的数组,地址计算方法类似,只是需要考虑更多维度的索引和步长。
例如,按行优先存储的三维数组D[m][n][p]的元素D[i][j][k]的地址计算公式为Loc(D[i][j][k]) = Loc(D[0][0][0]) + ((i * n * p + j * p + k) * C)。
列优先:Loc(D[i][j][k]) = Loc(D[0][0][0]) + (knm+j*m+i)*C

示例

数组A[9][3][5][8],首地址为100,每个元素占4个字节,求a[8][2][4][7]的地址

①行优先

100+(8358+258+48+7)*4

②列优先

100+(7539+439+29+8)*4

2)稀疏矩阵的转置

三元组顺序表

由于稀疏矩阵中含有大量的零元素,空间利用率很低,所以需要三元组顺序表来表示稀疏矩阵中的非零元素,它通过行优先的顺序将非零元素及其位置信息存储在一个线性表中,节省存储空间并简化运算

在这里插入图片描述
在这里插入图片描述

结构定义
typedef struct{int i,j;//该非零元的行下标和列下标ElemType e;
}Triple;
typedef struct{Triple data[MAXSIZE + 1];//非零元三元组表,data[0]未用int mu,nu,tu;//矩阵的行数、列数和非零元总数
TSMatrix;

①普通矩阵转置

for(col = 1;col <= nu;++col)for(row = 1;row <= mu;++row)T[col][row] = M[row][col];

②三元组顺序表转置稀疏矩阵

Status TransposeSMatrix(TSMatrix M, TSMatrix &T){//采用三元组表存储表示,求稀疏矩阵M的转置矩阵TT.mu = M.nu;  T.nu = M.mu;  T.tu = M.tu;if(T.tu){q = 1;for(col = 1; col <= M.nu; ++col)for(p = 1; p <= M.tu; ++p)if(M.data[p].j == col){T.data[q].i = M.data[p].j;  T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e;  ++q;}}return OK;
}//TransposeSMatrix

③稀疏矩阵的快速转置

如果能预先确定就诊M中每一列(即T中的每一行)的第一个非零元在b.data中应有的位置,那么在对a.data中的三元组一次作转置时,便可直接放到b.data中恰当的位置上去,提高运算效率。

为此,需要附设num和cpot两个向量。num[col]表示矩阵M中第col列中非零元的个数,cpot[col]指示M中第col列的第一个非零元在b.data中的恰当位置。显然有
cpot[1] = 1;
cpot[col] = cpot[col - 1] + num[col - 1], 2 <= col <= a.nu
在这里插入图片描述

接下来就可以利用num和cpot向量快速确定转置后各元素在三元组表中的位置,提高运行效率

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){//采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵TT.mu = M.nu;  T.nu = M.mu;  T.tu = M.tu;if(T.tu){for(col = 1; col <= M.nu; ++col)num[col] = 0;for(t = 1; t <= M.tu; ++t)++num[M.data[t].j];//求M中每一列含非零元个数cpot[1] = 1;//求第col列中第一个非零元在b.data中的序号for(col = 2; col <= M.nu; ++col)cpot[col] = cpot[col - 1] + num[col - 1];for(p = 1; p <= M.tu; ++p){col = M.data[p].j;  q = cpot[col];T.data[q].i = M.data[p].j;  T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e;  ++cpot[col];//当一列的第一个元素转置完成后,下一个需要转置的是三元组表的下一个位置}//for}//ifreturn OK;
//FastTransposeSMatrix

3)十字链表

十字链表是一种用于表示稀疏矩阵的特殊存储结构,它通过行优先的顺序将非零元素及其位置信息存储在一个线性表中。每个节点包含五个字段:行号、列号、值、向下指针和向右指针,从而形成一个十字交叉的链表结构。这种结构不仅节省了存储空间,还提高了运算效率,并使得对稀疏矩阵的操作更加灵活和高效。

在这里插入图片描述

结构定义

typedef struct OLNode{int i,j;//该非零元的行和列下标ElemType e;struct OLNode *right,*down;//该非零元所在行表和列表的后继链域
}OLNode; *OLink;typedef struct{OLink *rhead,*chead;int mu,nu,tu;//稀疏矩阵的行数、列数、非零元总数
}CrossList;

2、广义表

定义

广义表是一种非线性的数据结构,它允许表中的元素既可以是单个数据项(原子),也可以是另一个广义表。这种结构使得广义表能够表示复杂的嵌套关系和层次结构。广义表的特点包括其元素的多样性(可以是原子或其他广义表)、结构的灵活性(可以嵌套任意深度)以及操作的复杂性(如求表头、表尾等)。在存储上,广义表通常采用链式结构来表示,以方便处理其复杂的嵌套关系。

1)基本操作

①GetHead

获取广义表的第一个元素,可以是原子,可以是列表

②GetTail

除了广义表中第一个元素的所有其他元素的集合,无论该元素是什么,都需要在外面额外套上一个(),即使是空表,或该值本来就有()

该部分主要是在给出一个广义表时能正确获取表头和表尾

2)构造存储结构的两种方法

表头表尾

结构定义
typedef struct GLNode{ElemTag tag;//公共部分,用于区分原子结点和表结点union{//原子结点和表结点的联合部分AtomType atom;//atom是原子结点的值域,AtomType由用户定义struct{struct GLNode *hp,*tp;}ptr;//ptr是表结点的指针域,ptr.hp和[tr.tp分别指向表头和表尾};
}*GList;//广义表类型

示例:
A = ()
B = (e)
C = (a,(b,c,d))
D = (A,B,C)
E = (a,E)//递归表 E = (a,(a,(a,…)))
在这里插入图片描述

另一种方法我还没理解,就不在这里说了

3)递归算法

由于广义表的定义本身就具有一定的递归性,且其子表问题与其本身的问题具有极高相似度、关联性,所有递归算法与广义表操作具有极好的适配性

①求广义表深度

int GListDepth(GList L){//采用头尾链表存储结构,求广义表L的深度。if C!L) return 1// 空表深度1if (L—> tag == ATOM) return 0;// 原子深度 0for (max=0, pp=L; PP; pp=pp->ptr. tp) {dep = GListDepth(pp—>Ptr.hp);// 求以 pp—>ptr.hp 为头指针的子表深度if (dep > max) max = dep;}return max + 1//非空表的深度是各元素的深度的最大值+1
}// GListDepth

②复制广义表

Status CopyGList(GList &T, GList L) {// 采用头尾链表存储结构,由广义表L复制得到广义表T。if(!L)  T = NULL;// 复制空表else {if(!(T= (GList) malloc(sizeof(GL.Node))))exit(OVERFLOW);// 建表结点T -> tag = L -> tag;if (L—> tag == ATOM) T -> atom = L -> atom;// 复制单原子else {CopyGList(T-> ptr. hp, L->ptr. hp) ;// 复制广义表L->ptr.hp 的一个副本T->ptr.hpCopyGList(T—> ptr. tp, L->ptr. tp);// 复制广义表L->ptr.tp 的一个副本T->ptr.tp} // else} // elsereturn OK;
}// CopyGList

③创建广义表

三种情况:

  1. 带括弧的空白串
  2. 长度为1的单字符串
  3. 长度>1的字符串

显然,前两种情况为递归的终结状态,子表为空表或只含一个原子结点,后一种情况为递归调用

Status CreateGList (GList &L, SString S) {//采用头尾链表存储结构,由广义表的书写形式串S创建广义表L。设 emp="()"if (StrCompare(S, emp))L=NULL//创建空表else {if (! (L = (GList) malloc (sizeof (GLNode)))) exit (OVERFLOW); //建表结点if (StrLength(S)==1){L->tag = ATOM; L->atom =S;}// 创建单原子广义表else {L->tag = LIST; p = L;SubString (sub, S, 2, Strength(S)2) ;// 脱外层括号do// 重复建n 个子表sever(sub,hsub);// 从 sub中分离出表头串hsubCreateGList(p->ptr. hp,hsub);q = p;if (!StrEmpty(sub)){// 表尾不空if (!(p = (GLode * ) malloc (sizeof (GLNode))))exit (OVERFLOW) ;p->tag = LIST; q->ptr.tp = p;}//if}while (! StrEmpty (sub)) ;q—>ptr. tp = NULL;}//else} // elsereturn OK;
}// CreateGListStatus sever(SString &str, SString &hstr) {// 将非空串 str 分割成两部分:hsub 为第一个‘,’之前的子串,str 为之后的子串n= StrLength(str); i=0;k=0//k记尚未配对的左括号个数do {// 搜索最外层的第一个逗号++i;SubString(ch, str,i,1);if(ch =='(')  十十k;else if (ch==‘)’)  --k;} while (i<n && (ch! =','|| k! =0));if (i<n){SubString (hstr, str, 1, i—1)SubString(str, str, i+1, n—i)} else {StrCopy (hstr, str); ClearString(str) }
} // sever

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

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

相关文章

【Spring】Spring Web MVC基础入门~(含大量例子)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;什么是Spring Web MVC 1&#xff1a;Servlet 2&#xff1a;总结 二&#xff1a;MVC …

有向图的完全可达性(有向图搜索全路径的问题) C#DFs

在考察输入输出方面我觉得是道难题了 第一次遇见邻接表的数据结构该怎么声明 卡码网105 在力扣没找见完全相同的题 感觉需要多练习多复习这种类型的题 105. 有向图的完全可达性 题目描述 给定一个有向图&#xff0c;包含 N 个节点&#xff0c;节点编号分别为 1&…

登陆页面渗透测试常见的20种思路与总结

【渗透测试】16个实用谷歌浏览器插件分享 飞雪网络安全人才培养计划&#xff0c;绝对零区&#xff0c;公益教学&#xff01; 思路总结 1、之前是否已经留过后门&#xff0c;是&#xff0c;直接getshell&#xff0c;否&#xff0c;进行测试 2、SQL注入&万能密码&#xf…

qt QWebSocketServer详解

1、概述 QWebSocketServer 是 Qt 框架中用于处理 WebSocket 服务器端的类。它允许开发者创建 WebSocket 服务器&#xff0c;接受客户端的连接&#xff0c;并与之进行双向通信。WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议&#xff0c;它使得客户端和服务器之间的数…

掌握分布式系统的38个核心概念

天天说分布式分布式&#xff0c;那么我们是否知道什么是分布式&#xff0c;分布式会遇到什么问题&#xff0c;有哪些理论支撑&#xff0c;有哪些经典的应对方案&#xff0c;业界是如何设计并保证分布式系统的高可用呢&#xff1f; 1. 架构设计 这一节将从一些经典的开源系统架…

中小跨境卖家如何选择物流?

跨境物流作为电商交易的核心环节&#xff0c;其复杂性和多变性对卖家来说不言而喻。本文将为您详细解析跨境物流的七大流程、常见物流测评以及推荐的工具&#xff0c;帮助您在激烈的市场竞争中把握物流优势&#xff0c;提升业务效率和客户满意度。 跨境物流七大流程 1. 启运国出…

6大国有银行软开的薪资待遇清单

牛客上刷到一条关于计算机专业值得去的银行软开清单,其中对 6 大国有银行软开的薪资待遇分析我觉得很有必要同步给大家看一看。 截图信息来自牛客的漫长白日梦 其中邮储软开是最值得推荐的(offer 投票没输过),二线城市转正后第一个完整年的收入在 30 万左右,一线城市更高…

我们来学mysql -- EXPLAIN之ID(原理篇)

EXPLAIN之ID 题记ID 题记 2024美国大选已定&#xff0c;川普剑登上铁王座&#xff0c;在此过程中出谋划策的幕僚很重要&#xff0c;是他们决定了最终的执行计划在《查询成本之索引选择》中提到&#xff0c;explain的输出&#xff0c;就是优化器&#xff08;幕僚&#xff09;选…

蓝桥杯-网络安全比赛题目-遗漏的压缩包

小蓝同学给你发来了他自己开发的网站链接&#xff0c; 他说他故意留下了一个压缩包文件&#xff0c;里面有网站的源代码&#xff0c; 他想考验一下你的网络安全技能。 &#xff08;点击“下发赛题”后&#xff0c;你将得到一个http链接。如果该链接自动跳转到https&#xff0c;…

新疆高校大数据实验室案例分享

高校大数据实验室建设&#xff0c;企业可以提供技术支持、实训平台和项目案例&#xff0c;高校则提供科研和教学资源&#xff0c;实现产学研一体化。不仅有利于大数据技术的应用和人才培养也有利于区域发展。 泰迪与新疆合作的院校包括新疆大学、昌吉学院等 新疆大…

关于Flutter空安全升级方案整理

前言 Flutter 从 2.0 版本开始支持空安全&#xff08;Null Safety&#xff09;。dart 版本为&#xff1a; environment:sdk: ">2.12.0 < 3.0.0"升级到空安全后&#xff0c;由于语法的变动&#xff0c;基本上整个工程&#xff0c;代码都爆红&#xff0c;这对项…

干货 | 2024年数据要素白皮书(免费下载)

导读&#xff1a;白皮书在对比分析国际数据领域发展现状的基础上&#xff0c;围绕数据要素市场化配置改革这一主线&#xff0c;从数据高质量供给、数据创新应用、体制机制建设、产业探索方向四大方面展现了数据要素发展过程中&#xff0c;各类主体的新作为、新成效&#xff0c;…

RTT 内核基础学习

RT-Thread 内核介绍 内核是操作系统的核心&#xff0c;负责管理系统的线程、线程间通信、系统时钟、中断以及内存等。 内核位于硬件层之上&#xff0c;内核部分包括内核库、实时内核实现。 内核库是为了保证内核能够独立运行的一套小型的类似C库的函数实现子集。 这部分根据编…

六通道CAN集线器(协议型)

一、功能概述 SG_CanHub_600 是一款具有六路通道的工业级智能 CAN 数字隔离中继集线器。 SG_CanHub_600 能够实现信号再生、延长通信距离、提高总线负载能力、匹配不同速 率 CAN 网络&#xff0c;同时强大的 ID过滤功能可以极大降低 CAN 总线负荷&#xff0c;并具有故障指…

Web应用性能测试工具 - httpstat

在数字化时代&#xff0c;网站的性能直接影响用户体验和业务成功。你是否曾经在浏览网页时&#xff0c;遇到加载缓慢的困扰&#xff1f;在这个快速变化的互联网环境中&#xff0c;如何快速诊断和优化Web应用的性能呢&#xff1f;今天&#xff0c;我们将探讨一个强大的工具——h…

【Linux】从零开始使用多路转接IO --- 理解EPOLL的 LT水平触发模式 与 ET边缘触发模式

当你偶尔发现语言变得无力时&#xff0c; 不妨安静下来&#xff0c; 让沉默替你发声。 --- 里则林 --- 从零开始认识多路转接 1 EPOLL优缺点2 EPOLL工作模式 1 EPOLL优缺点 poll 的优点(和 select 的缺点对应) 接口使用方便&#xff1a;虽然拆分成了三个函数&#xff0c;…

kafka+zookeeper的搭建

kafka从2.8版本开始&#xff0c;就可以不用配置zookeeper了&#xff0c;但是也可以继续配置。我目前使用的kafka版本是kafka_2.12-3.0.0.tgz&#xff0c;其中前面的2.12表示是使用该版本的scala语言进行编写的&#xff0c;而后面的3.00才是kafka当前的版本。 通过百度网盘分享…

基础数据结构——队列(链表实现)

队列的性质 先进先出&#xff08;FIFO - First In First Out&#xff09;&#xff1a;最先加入队列的元素最先被移出后进后出&#xff08;后来的元素排在队尾&#xff09;只允许在队尾插入元素&#xff0c;在队首删除元素具有先来先服务的特点 链表实现队列 和之前创建链表相…

git原理与上传

言&#xff1a; git是一个软件&#xff0c;gitee/github是一个网站&#xff0c;这里有什么联系吗&#xff1f;我们身为一个程序员不可能不知道github&#xff0c;但是毕竟这是外国的网站&#xff0c;我们不翻墙的情况下&#xff0c;是无法访问的(或者就是太慢了&#xff0c;或…

亚信安全新一代WAF:抵御勒索攻击的坚固防线

近年来&#xff0c;勒索攻击已成为黑客的主要攻击手段。新型勒索攻击事件层出不穷&#xff0c;勒索攻击形势愈发严峻&#xff0c;已经对全球制造、金融、能源、医疗、政府组织等关键领域造成严重危害。如今&#xff0c;勒索攻击手段日趋成熟、攻击目标愈发明确&#xff0c;模式…