线性表概念及顺序表的实现

news2025/2/7 19:56:26

文章目录

  • 前言
  • 一、线性表
    • 1.定义
    • 2.特点
    • 3.一般线性表的抽象数据类型定义
  • 二、线性表的顺序存储(顺序表)
    • 1.基本概念
    • 2.数组实现顺序表
    • 3.顺序表中基本操作的具体实现
    • 4.顺序表总结
  • 总结


前言

  T_T此专栏用于记录数据结构及算法的(痛苦)学习历程,便于日后复习(这种事情不要啊)。所用教材为《数据结构 C语言版 第2版》严蔚敏。有关线性结构和抽象数据类型的概念,见数据结构与算法的基本概念


一、线性表

1.定义

  线性表:由0个或多个具有相同属性的数据元素组成的有限序列,常用(A0,A1…An)形式表示。例如26个英文字母(A,B,C…Z)就是一个线性表。

2.特点

  1.线性表是一个序列,也就是说数据元素存在先来后到的关系。好比一个数列,a0总是第一个出现。
  2.满足线性结构要求。
  3.线性表中元素的个数n (n>=0)定义为线性表的长度,n=0时称为空表。如果表中无元素,则为空表,n=0。
  我们常用的一维数组就是一个线性表。

3.一般线性表的抽象数据类型定义

  线性表作为一个相当灵活的数据结构,其长度可根据需要增长或缩短,即对线性表的数据元素不仅可以进行访问,而且可以进行插入和删除等操作。下面给出一般线性表的抽象数据类型定义:

ADT List{
数据对象: D={ai | ai∈ElemSet, i=l, 2, …,n, n>=Q}
数据关系: R=(<ai-1,ai>| ai-1,ai∈D, i=2, …, n}
基本操作:
InitList (&L)
操作结果:构造一个空的线性表L。
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList (&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
ListEmpty(L)
初始条件:线性表L已存在。
操作结果:若L为空表,则返回true, 否则返回false。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
GetElem(L,i,&e)
初始条件:线性表L已存在,且1<=i<=ListLength(L)。
操作结果:用e返回L中第i个数据元素的值。
LocateElem(L,e)
初始条件:线性表L已存在。
操作结果:返回L中第1个值与e相同的元素在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无定义。
ListInsert(&L,i,e)
初始条件:线性表L已存在,且1<=i<=ListLength(L)+1。
操作结果:在 L中第i个位置之前插入新的数据元素 e, L的长度加1。
ListDelete(&L,i)
初始条件:线性表L已存在且非空,且1<=i<=ListLength(L)。
操作结果:删除L的第i个数据元素,L的长度减1。
ListTraverse(&L,visited())
初始条件:线性表L已经存在
操作结果:对线性表L进行遍历,在遍历过程中对线性表中每个元素调用visited()
}ADT List

注:
(1)抽象数据类型仅是一个模型的定义,并不涉及模型的具体实现,因此这里描述中所涉及的参数不必考虑具体数据类型。在实际应用中,数据元素可能有多种类型,到时可根据具体需要选择使用不同的数据类型。
(2) 上述抽象数据类型中给出的操作只是基本操作,由这些基本操作可以构成其他较复杂的操作。
(3)对于不同的应用, 基本操作的接口可能不同。
(4)由抽象数据类型定义的线性表, 可以根据实际所采用的存储结构形式, 进行具体的表示和实现。

二、线性表的顺序存储(顺序表)

1.基本概念

  线性表的顺序表示(又称顺序表)指的是用一组地址连续的存储单元依次存储线性表的数据元素, 这种表示也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为顺序表(Sequential List)。其特点是,逻辑上相邻的数据元素, 其物理次序也是相邻的。
  假设线性表的每个元素需占用m个存储单元,并以所占的第一个单元的存储地址LOC(q)作为数据元素的存储起始位置。则线性表中第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
       LOC(ai+1)=LOC(ai)+m
  从而线性表第i个元素存储位置:
       LOC(ai)=LOC(q)+(i-1)*m.

2.数组实现顺序表

  在高级语言中,通常都用数组来描述数据结构中的顺序存储结构。由于线性表的长度可变,且所需最大存储空间随问题不同而不同,则在C语言中可用动态分配的一维数组表示线性表。
  下面给出一般实现过程:

#define MAXSIZE 100   //顺序表可能达到的最大长度
typedef struct 
{
	ElemType *elem;   //起始地址,即第一个元素存储地址;ElemType为某一数据类型或用户自定义的数据类型
	int length;       //当前顺序表长度
}SqList;
SqList L;

//在c语言中,用malloc实现数组内存动态分配,需要头文件<stdlib.h>
L.data=(ElemType *)malloc(sizeof(ElemType)*MAXSIZE); 
//malloc(n)用于创建一个可以存放n个字节的空间,并返回其首地址
//(ElemType *)用于指针类型强制,此处用于告诉编译器是如何分配的空间。
//以(int *)malloc(sizeof(int)*100)为例
//表示开辟了一个4*100=400字节的空间,其中空间分配为每4字节为一个数据元素,而不是每2字节。
free(p):释放指针p所指变量的存储空间,即彻底删除一个变量

//在c++中,用new来实现数组内存动态分配
new 类型名T (初值列表):用于申请存放T类型对象的内存空间,并以初值列表赋初值,若成功则返回T类型指针,指向分配的内存,若失败则返回0(NULL): int *p=new int(10); //成功执行后,p中存放新分配的内存地址,且该地址空间存放值为10
delete 指针p:释放指针p指向的内存,p必须是new操作的返回值
例: delete p;

  考虑多项式:x³+0.5x+1的存储,从而既要存储其指数项,也要存储其对应的系数项:

#define MAXSIZE 100   //多项式可能达到的最大长度
typedef struct 
{
float coef;    //系数
int expn;      //指数
) Polynomial; 
typedef struct 
{ 
Polynomial *elem; 
int length; 
}SqList;
SqList L;
L.data=(Polynomial *)malloc(sizeof(Polynomial)*MAXSIZE); 

  将L定义为SqList类型的变量,便可以利用L.elem[i-1]访间表中位置序号为i的元素
在这里插入图片描述

3.顺序表中基本操作的具体实现

  下面给出一个实现案例:

#include <iostream>
#include <string.h>
using namespace std;

#define maxsize 10  //顺序表最大长度
#define ok 1
#define fail 0
#define true 1
#define false 0
#define Not_Exist -1
#define overflow -2

typedef int Status;
typedef int book;
typedef struct {
	book* start;
	int length;
}Sqlist;

//初始化,创建顺序表
Status Creatlist(Sqlist &l)
{
	l.start = new book[maxsize];
	if (!l.start)return fail;
	l.length = 0;

	for (int i = 0; i < maxsize; i++)
	{
		cin >> l.start[i];
		l.length++;
	}
	return ok;
}
//销毁顺序表
Status destoryList(Sqlist &l)
{
	if (!l.start)return Not_Exist;  //判断线性表是否存在
	delete[]l.start;
	l.start=NULL; //销毁后,指针仍然存在,指向随机,销毁的只是原来存储的值,计算机内存空间地址是无法销毁的,因此需要在delete后给指针赋NULL
	return ok;
}
//清空顺序表
Status clearList(Sqlist& l)
{
	if (!l.start)return Not_Exist;
	l.length = 0;
	return ok;
}
//检测顺序表是否空
Status Listempty(Sqlist l)
{
	if (!l.start)return Not_Exist;
	if (l.length == 0)
		return true;
	return	false;
}
//返回顺序表长度
Status Listlength(Sqlist l)
{
	if (!l.start)return Not_Exist;
	return l.length;
}
//得到顺序表中某个值
Status Getelem(Sqlist l, int i, book& e)
{
	if (!l.start)return Not_Exist;
	if (i<1 && i>l.length)return fail;
	e = l.start[i - 1];
	return ok;
}
//检查顺序表中是否存在某个值及其位置
Status Locateelem(Sqlist l,book e)
{
	if (!l.start)return Not_Exist;
	for (int i = 1; i <= l.length; i++)
		if (e == l.start[i-1])
			return i;
	return 0;
}
//返回顺序表中某个值的前序
book Priorelem(Sqlist l, book cur_e,book &pre_e)
{
	int i = Locateelem(l, cur_e);
	if (i == 1)
		return Not_Exist;
	pre_e=l.start[i - 2];
	return ok;
}
//返回顺序表中某个值的后序
book Nextelem(Sqlist l, book cur_e, book& next_e)
{
	int i = Locateelem(l, cur_e);
	if (i == l.length)
		return Not_Exist;
	next_e = l.start[i];
	return ok;
}
//插入一个数据元素
Status Listinsert(Sqlist &l, int pos, book e)
{
	if (!l.start)return Not_Exist;
	if (l.length == maxsize)return overflow;
	if (pos < 1 || pos > l.length + 1)return fail;
	for (int i=l.length-1; i >=pos-1; i--)
		l.start[i + 1] = l.start[i];
	l.start[pos - 1] = e;
	l.length++;
	return ok;
}
//删除一个数据元素
Status Listdelete(Sqlist& l, int pos)
{
	if (!l.start)return Not_Exist;
	if (l.length == 0)return overflow;
	if (pos < 1 || pos > l.length + 1)return fail;
	for (int i = pos - 1; i < l.length-1; i++)
		l.start[i] = l.start[i+1];
	l.length--;
	return ok;
}
//遍历顺序表
Status Traverselist(Sqlist &l)
{
	if (!l.start)return Not_Exist;
	for (int i = 0; i < l.length; i++)
		cout << l.start[i] << "  ";  //这里可以是任何合法操作

	return ok;
}

Sqlist l;
book e1;
book e2 = 7;
book pre_e;
book next_e;
int main()
{
	//测试
	Creatlist(l);
	cout << "输入测试用例:" << endl;//这里以1-10作为测试用例
	cout << l.start << endl << l.length << endl;
	Traverselist(l); cout << endl;
	cout << Listlength(l) << endl;
	cout << Getelem(l, 5, e1) << " " << e1 << endl;
	cout << Priorelem(l, 5, pre_e) << " " << pre_e << endl;
	cout << Nextelem(l, 5, next_e) << " " << next_e << endl;
	cout << Locateelem(l, e2) << " " << e2 << endl;
	Listdelete(l, 1);
	cout << l.start[0] << endl;
	destoryList(l);
	cout << l.start << endl; 
	return 0;
}

测试结果:
在这里插入图片描述

4.顺序表总结

  对于线性表的顺序存储,可以采用静态数组或动态数组实现,为了便于数据扩充,常采用动态数组的方式。
  顺序表可以随机存取表中任一元素(随机存取),其存储位置可用一个简单、直观的公式来表示。然而从另一方面来看,这个特点也造成了这种存储结构的缺点:在做插入或删除操作时,需移动大量元素。另外由于数组有长度相对固定的静态特性,当表中数据元素个数较多且变化较大时,操作过程相对复杂,必然导致存储空间的浪费。所有这些问题,都可以通过线性表的另一种表示方法——链式存储结构来解决。线性表的链式存储


总结

  路漫漫其修远兮,吾将上下而开摆。
  有任何疑问和补充,欢迎交流。(但我显然不会)

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

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

相关文章

计算机虚拟机服务器中了mallox勒索病毒怎么办Mallox勒索病毒解密流程工具

在当今社会&#xff0c;人们的工作生活离不开网络&#xff0c;尤其企业离不开网络办公&#xff0c;网络为企业提供了极大便利&#xff0c;大大提升了企业的生产效率与办公水平&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时也为企业的数据带来严重威胁。近…

第10章 物理安全要求

10.1 站点与设施设计的安全原则 假如没有对物理环境的控制&#xff0c;任何管理的、技术的或逻辑的访问控制技术都无法提供足够的安全性。 如果怀有恶意的人员获取了对设施及设备的物理访问权&#xff0c;那么他们几乎可以为所欲为&#xff0c;包括肆意破坏或窃取、更改数据。…

管理和维护索引

本文接上一篇创建、更改、删除索引继续讨论如何管理和维护SinoDB数据库的B树索引。 1. 索引的好处 ① 基于索引的排序 一列或多列的索引可用于按序取回数据。使用索引读取数据可以让数据库服务器按照请求的顺序直接返回数据&#xff0c;免去了排序的操作。 ② 强制保证唯一性…

使用matlab GUI设计离线问卷

很久没有更新了。没有更新的日子&#xff0c;也在努力学习&#xff0c;坚定了继续搞科研的决心&#xff0c;至死不渝。希望我们每个人都能有远大的理想&#xff0c;并为之付出不懈的奋斗。 目录 一、为什么 二、怎么设计 1. 问题和答案的显示 2. 答案的记录和保存 三、代…

V神演讲展望Web3发展并认为可引入人工智能

前言 2024 香港 Web3 嘉年华期间&#xff0c;以太坊联合创始人 Vitalik Buterin 发表主旨演讲《Reaching the Limits of Protocol Design》。以下是演讲内容&#xff1a; 区块链与ZK-SNARKS 我们用来构建协议的技术类型在过去 10 年里发生了很大变化。那么&#xff0c;当 2…

德国高速主轴SycoTec代理 高精度高转速主轴一览

速科德电机科技&#xff0c;作为德国高速主轴品牌SycoTec代理以及亚太服务中心&#xff0c;一直致力于将最先进、最可靠的高速电主轴技术带给广大机械加工企业。在现代精密机械制造业中&#xff0c;高速电主轴的应用已经变得不可或缺&#xff0c;而SycoTec高速电主轴以其卓越的…

【七 (1)FineBI FCP模拟试卷-股票收盘价分析】

目录 文章导航一、字段解释二、需求三、操作步骤1、添加计算字段&#xff08;每月最后一天的收盘价&#xff09;2、绘制折线图 文章导航 【一 简明数据分析进阶路径介绍&#xff08;文章导航&#xff09;】 一、字段解释 Company Name&#xff1a;公司名称 Date&#xff1a;…

UE5 C++ 创建3DWidgete 血条 再造成伤害

一&#xff0e;创建 二&#xff0e;&#xff35;&#xff29;里声明变量 创建类 public:UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyWidget")float CurrentHealth 100.0f;UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyWidget"…

【嵌入式】嵌入式开发中常见的面试题(持续更新中)

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

Linux--进程间的通信--进程池

进程间的通信–匿名管道 进程池的概念 进程池是一种将多个进程组织起来以执行特定任务的机制。它由多个预先创建好的资源进程和一个管理进程组成。这些资源进程被管理进程负责分配和调度&#xff0c;用于处理任务。 当有新的任务提交时&#xff0c;管理进程会从进程池中取出一…

主线程捕获子线程异常

正常情况下使用多线程出现异常时&#xff0c;都是按照单个任务去处理异常&#xff0c;在线程间不需要通信的情况下&#xff0c;任务之间互不影响&#xff0c;主线程也不必知道子线程是否发成异常。 那么只需要处理子线程异常即可 Task.Run(() > {try{throw new Exception(&…

苍穹外卖学习记录(二)

本节&#xff0c;主要是学习业务逻辑&#xff0c;我们以菜品管理为例&#xff1a; 在实现这部分前&#xff0c;我们要完成Mybatis的配置&#xff0c;即指定映射的mapper.xml文件路径以及对应的实体类&#xff0c;这部分配置是在application.yml文件中实现的。 mybatis:#mapper…

计算机网络(四)网络层

网络层 基本概念 网络互联&#xff1a; 将两个以上的计算机网络&#xff0c;通过一定的办法&#xff0c;用一种或多种通信处理设备(即中间设备)相互连接起来&#xff0c;以构成更大的网络系统。中间设备又称中间系统或中继系统 中继系统分为4种&#xff1a; 物理层中继系统…

thinkphp 框架封装curl请求

tp6 或者 tp8框架 在框架的app/common.php 文件里加一些方法就可以 app\common.php 在这个文件里加 以下代码 就可以实现基于 curl的请求方法 (记得要开启 php的curl扩展) 查看方法 cmd里输入 php -m if (!function_exists(get)) {/*** 发送get请求* param string $url 请求…

ChatGPT实用指南2024

随着ChatGPT技术的演进&#xff0c;越来越多的人开始在工作中利用此工具。以下是关于ChatGPT的实用指南&#xff0c;适合不太熟悉此技术的朋友参考。 一、ChatGPT概述 1. ChatGPT是什么&#xff1f; ChatGPT是基于OpenAI开发的GPT大型语言模型的智能对话工具。它能够通过自然语…

前端框架模板

前端框架模板 1、vue-element-admin vue-element-admin是基于element-ui 的一套后台管理系统集成方案。 **功能&#xff1a;**https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能 **GitHub地址&#xff1a;**GitHub - PanJiaChen/vue-element-admin: :t…

网盘——添加好友

关于添加好友&#xff0c;过程如下&#xff1a; A、首先客户端A发送加好友的请求&#xff0c;发送的信息包括双方的用户名 B、当服务器收到请求之后&#xff0c;服务器将数据库中在线用户查找出来&#xff0c;如果客户端B已经是你的好友了&#xff0c;服务器告诉客户端A他已经…

【深度学习】深度学习md笔记总结第5篇:神经网络与tf.keras,学习目标【附代码文档】

深度学习笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;深度学习课程&#xff0c;深度学习介绍要求,目标,学习目标,1.1.1 区别,学习目标,学习目标。TensorFlow介绍&#xff0c;2.4 张量学习目标,2.4.1 张量(Tensor),2.4.2 创建张量的指令,2.4.3 张量…

Sublime Text下载,安装,安装插件管理器,下载汉化插件

SublimeTest官网 © Sublime Text中文网 下载安装 一路点击安装即可 安装插件管理器 管理器官网安装 - 包控制 (packagecontrol.io) 手动安装将3 位置点击网址下载 再打开SublimeTest 点击 选择第一个Browse Packages..... 将会跳转到文件夹中 进入上一个文件夹 在进入…

【模拟】Leetcode 提莫攻击

题目讲解 495. 提莫攻击 算法讲解 前后的两个数字之间的关系要么是相减之差 > 中毒时间 &#xff0c;要么反之 那即可通过示例&#xff0c;进行算法的模拟&#xff0c;得出上图的计算公式 class Solution { public:int findPoisonedDuration(vector<int>& time…