数据结构-线性表的顺序表示

目录

  • 前言
  • 一、线性表
    • 1.1 线性表的概念
    • 1.2 线性表的逻辑特征
  • 二、线性表的抽象数据类型
  • 三、线性表的顺序表示和实现
    • 3.1 线性表的顺序表示
    • 3.2 基本操作的实现
  • 总结

前言

本篇文章介绍线性表的基本概念,并使用顺序存储结构实现线性表。
本篇文章使用的程序设计语言为C语言,需要读者掌握C语言的指针、结构体和动态内存管理的知识。
如果您对C语言的指针不熟悉,请阅读https://blog.csdn.net/pyc68/article/details/135181228
如果您对C语言的结构体不熟悉,请阅读https://blog.csdn.net/pyc68/article/details/135211015
如果您对C语言的动态内存管理不熟悉,请阅读https://blog.csdn.net/pyc68/article/details/135737056

一、线性表

1.1 线性表的概念

概念:线性表是具有相同特性的数据元素的一个有限序列
( a 1 , a 2 , ⋯ , a i − 1 , a i , a i + 1 , ⋯ , a n ) ⏟ \underbrace{(a_1,a_2,\cdots,a_{i-1},a_i,a_{i+1},\cdots,a_n)} (a1,a2,,ai1,ai,ai+1,,an)

数据元素

数据元素 a 1 a_1 a1称为线性表的起始结点
数据元素 a n a_n an称为线性表的终端结点
数据元素 a i − 1 a_{i-1} ai1称为数据元素 a i a_i ai直接前驱
数据元素 a i + 1 a_{i+1} ai+1称为数据元素 a i a_i ai直接后继
下标 i i i,称为数据元素的序号,表示数据元素在线性表中的位置,称为第 i i i个数据元素 ( 1 ≤ i ≤ n ) (1 \leq i \leq n) 1in
n n n表示数据元素的总个数,即线性表的长度,当 n = 0 n=0 n=0时,称为空表;当 n > 0 n>0 n>0时,称为非空线性表

1.2 线性表的逻辑特征

在非空线性表中,线性表有以下特征

  • 有且仅有一个起始结点 a 1 a_1 a1,它没有直接前驱,仅有一个直接后继 a 2 a_2 a2
  • 有且仅有一个终端结点 a n a_n an,它没有直接后继,仅有一个直接前驱 a n − 1 a_{n-1} an1
  • 其余的内部结点 a i ( 2 ≤ i ≤ n ) a_i(2 \leq i \leq n) ai2in都有且仅有一个直接前驱 a i − 1 a_{i-1} ai1和一个直接后继 a i + 1 a_{i+1} ai+1

二、线性表的抽象数据类型

线性表的抽象数据类型定义如下:

ADT List
{数据对象: D={ai | ai属于数据元素集合,(i=1,2,...n,n ≥ 0)};数据关系: S={<a(i-1),ai>| a(i-1),ai属于D(i=2,3,...,n)}基本操作:createNullList(&L)操作结果:创建一个空表destroyList(&L)初始条件:线性表L存在操作结果:销毁一个线性表LclearList(&L)初始条件:线性表L存在操作结果:将线性表L重置为一个空表isEmpty(L)初始条件:线性表L存在操作结果:判断线性表L是否为空表listLength(L)初始条件:线性表L存在操作结果:返回线性表L中的元素个数		getElem(L,i,&e)初始条件:线性表L存在,1<= i <= listLength(L)操作结果:用e返回线性表L中第i个数据元素的值locateElem(L,e,compare())初始条件:线性表L存在,compare()是数据元素判断函数操作结果:返回L中第1个与e满足compare()的数据元素的序号i(1 <= i <= listLength(L))若这样的数据元素不存在则返回0	priorElem(L,cur_e,&pre_e)初始条件:线性表L存在操作结果:若cur_e是L的数据元素,且不是起始结点,则用pre_e返回它的前驱结点否则操作失败,pre_e无意义nextElem(L,cur_e,&next_e)初始条件:线性表L存在操作结果:若cur_e是L的数据元素,且不是终端结点,则用next_e返回它的后继结点否则操作失败,next_e无意义				insertElem(&L,i,e)初始条件:线性表L存在,1<= i <= ListLength(L)+1操作结果:在线性表的第i个位置插入一个元素e,L的长度加1deleteElem(&L,i)初始条件:线性表L存在,1<= i <= listLength(L)操作结果:删除线性表的第i个元素,L的长度减1traverseList(&L,visited())初始条件:线性表L存在操作结果:依次对线性表中每个元素调用visited()}ADT List

三、线性表的顺序表示和实现

3.1 线性表的顺序表示

顺序表的顺序表示又称为顺序存储结构或顺序映像
顺序存储定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构

线性表 ( a 1 , a 2 , ⋯ , a i − 1 , a i , a i + 1 , ⋯ , a n ) (a_1,a_2,\cdots,a_{i-1},a_i,a_{i+1},\cdots,a_n) (a1,a2,,ai1,ai,ai+1,,an)
顺序存储 ∣ ⋯ ∣ a 1 ∣ a 2 ∣ ⋯ ∣ a i − 1 ∣ a i ∣ a i + 1 ∣ ⋯ ∣ a n ∣ ⋯ ∣ ‾ ‾ \underline{\overline{|\cdots|a_1|a_2|\cdots|a_{i-1}|a_i|a_{i+1}|\cdots|a_n|\cdots|}} a1a2ai1aiai+1an
a 1 a_1 a1存储位置称为线性表的起始位置或基地址
线性表顺序存储结构占用一片连续的存储空间,知道某个元素的存储位置就可以计算其他元素的存储位置
假设线性表的每个元素占用 c c c个存储单元,则第 i + 1 i+1 i+1个数据元素的存储位置和第 i i i个数据元素的存储位置之间满足关系(用 l o c ( a i ) loc(a_i) loc(ai)表示数据元素的存储位置) l o c ( a i + 1 ) = l o c ( a i ) + c loc(a_{i+1})=loc(a_i)+c loc(ai+1)=loc(ai)+c
由此,所有数据元素的存储位置均可由第一个数据元素的存储位置得出:
l o c ( a i ) = l o c ( a 1 ) + ( i − 1 ) × c loc(a_i)=loc(a_1)+(i-1) \times c loc(ai)=loc(a1)+(i1)×c

3.2 基本操作的实现

基本操作的实现,在C语言使用函数表示基本操作
使用结构体类型定义一个线性表

//定义返回值状态码
#define SUCCESS 1
#define ERROR   0//这里假设元素的数据类型为char
typedef char ElemType;//定义一个线性表
struct SeqList {int MAXNUM;			//线性表的最大容量(元素个数)int n;				//线性表中实际的元素个数,n <= MAXNUMElemType* element;	//存放线性表元素,element[0],element[1]...element[n-1]
};//定义一个SeqList的指针类型
typedef struct SeqList* PSeqList;

由于线性表的基本操作较多,这里只将一些常见的操作。
由于是使用顺序存储结构实现线性表,此时可以称线性表为顺序表

  1. 创建空顺序表
    step1:首先使用malloc()函数创建一个struct SeqList大小的空间
    step2:然后使用malloc()函数创建一个(sizeof(ElemType)*m)大小的空间
    step3:将MAXNUM设置为m,将n设置为0(表示当前顺序表为空)

    //2.1 创建一个空顺序表
    PSeqList createNullList_seq(int m)
    {PSeqList palist = (PSeqList)malloc(sizeof(struct SeqList));if (NULL == palist)				//判断申请空间是否成功{printf("malloc Fail!\n");return NULL;}palist->element = (ElemType*)malloc(sizeof(ElemType) * m);if (NULL == palist->element)	{printf("malloc Fail!\n");free(palist);palist = NULL;return NULL;}palist->MAXNUM = m;palist->n = 0;return palist;
    }
    
  2. 销毁顺序表
    由于这里使用malloc()创建SeqList结点,则需要使用二级指针才能完成

    //2.2 销毁一个顺序表
    void destroyList_seq(PSeqList* palist)
    {assert(*palist);assert((*palist)->element);free((*palist)->element);(*palist)->element = NULL;free(*palist);*palist = NULL;
    }
    
  3. 顺序表的查找
    从表的一端开始,逐个进行比较。找到返回该元素的位置序号,否则返回ERROR(表示未找到)

    //2.6 查找与指定值e相同数据元素的位置
    int locateElem_seq(PSeqList palist, ElemType e)
    {assert(palist);int i = 0;for (i = 0; i < palist->n; i++)if (e == palist->element[i])return i + 1;            //i+1表示第几个元素,即element[i]return ERROR;
    }
    

    算法分析
    平均查找长度ASL(Average Search Length):为确定数据元素在表中的位置,需要与给定值进行比较的关键字的个数的期望叫做查找算法的平均查找长度
    对于n个数据元素的表,查找成功时 A S L = ∑ n i = 1 P i C i ASL=\underset{i=1}{\overset{n}{\sum}}P_iC_i ASL=i=1nPiCi
    P i P_i Pi为第i个数据元素被查找的概率
    C i C_i Ci找到第 i i i个数据元素需要比较的次数
    顺序查找的平均查找长度: A S L = P 1 + 2 P 2 + ⋯ + ( n − 1 ) P n − 1 + n P n ASL=P_1+2P_2+\cdots+(n-1)P{n-1}+nP_n ASL=P1+2P2++(n1)Pn1+nPn
    假设每个记录的查找概率相等,则
    A S L s s = ∑ n i = 1 P i C i = 1 n ∑ n i = 1 i = n + 1 2 ASL_{ss}=\underset{i=1}{\overset{n}{\sum}}P_iC_i=\frac{1}{n}\underset{i=1}{\overset{n}{\sum}}i=\frac{n+1}{2} ASLss=i=1nPiCi=n1i=1ni=2n+1
    其中 ∑ n i = 1 i = n ( n + 1 ) 2 其中\underset{i=1}{\overset{n}{\sum}}i=\frac{n(n+1)}{2} 其中i=1ni=2n(n+1)
    则这个算法的时间复杂度 T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n)
    则这个算法的空间复杂度 S ( n ) = O ( 1 ) S(n)=O(1) S(n)=O(1)

  4. 顺序表的插入

  5. 顺序表的删除

总结

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

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

相关文章

使用ANSI转义序列设置终端文本颜色

在使用ANSI转义序列设置终端文本颜色时&#xff0c;背景颜色和文本&#xff08;前景&#xff09;颜色的区分主要通过不同的ANSI代码来实现。ANSI转义序列使用格式为\033[代码m的结构&#xff0c;其中\033是转义字符&#xff08;等同于\e&#xff09;&#xff0c;m指示颜色设置的…

Python with MATLAB

Python with MATLAB 原文&#xff1a;Python with MATLAB - 知乎 (zhihu.com) 我问来自俄罗斯的实习生&#xff0c;你对网上争辩MATLAB和Python谁好谁坏有什么看法。实习生表示他不会Python&#xff0c;但是只要能完成老板布置的工作&#xff0c;哪个语言都无所谓。再说了&am…

c#调用c++生成的dll,c++端使用opencv, c#端使用OpenCvSharp, 返回一张图像

c代码&#xff1a; // OpenCVImageLibrary.cpp #include <opencv2/opencv.hpp> #include <vector> extern "C" { __declspec(dllexport) unsigned char* ReadImageToBGR(const char* filePath, int* width, int* height, int* step) { cv::Mat i…

事件驱动架构详解:触发与响应构建高效系统

目录 前言1. 事件驱动架构概述1.1 什么是事件1.2 事件驱动架构的核心概念 2. 事件驱动架构的实现2.1 基于消息队列的实现2.2 基于发布-订阅模式的实现2.3 基于流处理的实现 3. 事件驱动架构的优势3.1 松耦合性3.2 可扩展性3.3 异步处理3.4 灵活性 4. 事件驱动架构的应用场景4.1…

【深度学习】记录为什么没有调用GPU

排查CLIP为什么评测推理没有调用GPU&#xff0c;主要是这个代码&#xff1a;https://github.com/OFA-Sys/Chinese-CLIP/blob/master/cn_clip/eval/extract_features.py 第一次认为&#xff1a;因为model并没有to.cuda()。 但是又发现&#xff0c;model.cuda(args.gpu) # 已经加…

机器学习常见知识点 3:Boosting集成学习技术和XGB、LGB

文章目录 1、Boosting 的工作原理常见的 Boosting 算法优点和缺点如何进行加权投票 2、XGB1. XGBoost中的梯度提升2. 目标函数3. 树的构建与优化4. 处理缺失值与特征重要性 3、LGB核心特征1. 基于直方图的决策树学习2. 叶子优先策略3. 处理类别特征4. 缺失值处理 工作原理数据预…

镜像发布至dockerHub

1、login 没有账号的话去注册一个 https://hub.docker.com docker login 输入账号密码和账号2、修改镜像名格式 可以直接招我的修改 格式为你的 hub名/镜像名 3、推送

svm和决策树基本知识以及模型评价以及模型保存

svm和决策树基本知识以及模型评价以及模型保存 文章目录 一、SVM1.1&#xff0c;常用属性函数 二、决策树2.1&#xff0c;常用属性函数2.2&#xff0c;决策树可视化2.3&#xff0c;决策树解释 3&#xff0c;模型评价3.1&#xff0c;方面一&#xff08;评价指标&#xff09;3.2&…

DockerHub 镜像加速

Docker Hub 作为目前全球最大的容器镜像仓库&#xff0c;为开发者提供了丰富的资源。Docker Hub 是目前最大的容器镜像社区&#xff0c;DokcerHub的不能使用,导致在docker下pull镜像无法下载,安装kubernetes镜像也受到影响,下面请看解决方式。 1.加速原理 Docker下载加速的原理…

Android基于MediaBroswerService的App实现概述

mSession.setPlaybackState(mStateBuilder.build()); // 5. 关联 SessionToken setSessionToken(mSession.getSessionToken()); } } 根据包名做权限判断之后&#xff0c;返回根路径 Override public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundl…

如何生成protobuf文件

背景 protobuf是一种用于序列化结构数据的工具&#xff0c;实现数据的存储与交换&#xff0c;与编程语言和开发平台无关。 序列化&#xff1a;将结构数据或者对象转换成能够用于存储和传输的格式。 反序列化&#xff1a;在其他的计算环境中&#xff0c;将序列化后的数据还原为…

FreeBSD通过CBSD管理低资源容器jail 网络NAT配置

jail容器里的系统有时候并不需要公开的地址&#xff0c;所以给它们配置内网地址即可。但是这些系统一般都有上网的需求&#xff0c;这时候可以使用nat进行解决。 CBSD可以配置NAT规则&#xff0c;只需要命令cbsd natcfg&#xff0c;配置好后cbsd naton启动即可&#xff1a; % …

Vue3.4新增的defineModel的使用

define-model的作用 在3.3及之前的版本&#xff0c;父子组件之间的通讯&#xff0c;一直都是靠props&#xff08;父传子&#xff09;和emit&#xff08;子传父&#xff09;来实现。而define-model整合了这两种方法&#xff0c;只需要在父组件中定义define-model的方法&#xf…

Spring容器中的Bean作用域

在Spring框架中&#xff0c;开发者确实主要关注两件事&#xff1a;开发Bean和配置Bean。Spring容器负责根据配置文件或注解来创建Bean实例&#xff0c;并通过依赖注入&#xff08;DI&#xff09;来管理Bean之间的依赖关系&#xff0c;这体现了控制反转&#xff08;IoC&#xff…

GIT回滚

1. 使用 git revert git revert 命令会创建一个新的提交&#xff0c;这个提交会撤销指定提交的更改。这通常用于公共分支&#xff08;如 main 或 master&#xff09;&#xff0c;因为它不会重写历史。 git revert HEAD # 撤销最近的提交 # 或者指定一个特定的提交哈希值 …

实际中应对网络丢包故障的方法

1.网络数据包发送时通时断&#xff0c;丢包严重 故障现象&#xff1a;通常故障发生时&#xff0c;该方向网络出现震荡性中断。使用Ping命令测试&#xff0c;发现在一段时间内数据包发送延时比正常值略高&#xff0c;间隔一小段时间数据包又全部丢失&#xff0c;丢包率超过60%&a…

Net开源项目推荐-WPF控件样式篇

Net开源项目推荐-WPF控件样式篇 HandyControlWPFDeveloperswpf-uidesignLive-ChartsAvalonDock HandyControl WPF控件库,比较常用的WPF开源控件库&#xff0c;对WPF原有控件样式都进行了重写和扩展&#xff0c;也增加了许多特别的控件&#xff0c;非常好用 github仓库&#x…

Day14—基于Langchain-chatchat搭建本地智能

一、基于Langchain-chatchat搭建本地智能 知识问答系统 1、项目介绍 基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现&#xff0c;开一种利用 langchain 思想实现的基于本地知识库的问答应用&#xff0c;目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知…

贪心+动归1

​​​​​​​​​​​​​​跳跃游戏 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0…

Claude3.5:编码螃蟹游戏就是这么轻松

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则…