【数据结构】顺序表:尾部操作我很行,随机访问我超快!!!

news2024/11/16 11:58:05

顺序表的模拟实现

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

文章目录

  • 顺序表的模拟实现
    • 1.线性表
    • 2.顺序表
      • 2.1概念结构
      • 2.2顺序表的模拟实现
        • 2.2.1顺序表的初始化
        • 2.2.2顺序表的销毁
        • 2.2.3尾插数据
        • 2.2.4尾删数据
        • 2.2.5头插数据
        • 2.2.6头删数据
        • 2.2.7中间插入数据
        • 2.2.8中间删除数据
        • 2.2.9打印顺序表
        • 2.2.10查找数据
        • 2.2.11复用Insert和Erase实现尾部操作和头部操作
      • 2.3顺序表的优缺点
    • 3.顺序表OJ题目训练

 

1.线性表

  线性表 (linear list) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

  线性表在逻辑结构是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的

 

💡ps:

  逻辑结构:想象的该数据结构在内存中的存储方式,逻辑结构便于我们的思考。

  物理结构:实际的该数据结构在内存中的存储方式。

例如,C语言中的二维数组int arr[M][N]

逻辑结构:M行,N列的元素集合,不是连续存放的

物理结构:1行,M*N列的元素集合,是连续存放的

 

线性表在物理上存储时,通常以数组和链式结构的形式存储

在这里插入图片描述

 

2.顺序表

 

2.1概念结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。(静态数组)

    在这里插入图片描述

  2. 动态顺序表:使用动态开辟的数组存储。(malloc动态开辟空间)

    在这里插入图片描述

     

2.2顺序表的模拟实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表

SeqList.h中的声明(因为需要通过函数来修改顺序表,所以要传址)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLDateType;

//顺序表的成员
typedef struct SeqList
{
	SLDateType* a;//顺序表的首元素地址
	size_t size;//顺序表的数据个数
	size_t capacity;//顺序表的容量
}SL;

void SLInit(SL* ps);//顺序表的初始化

void SLDestroy(SL* ps);//顺序表的销毁

//尾部操作
void SLPushBack(SL* ps, SLDateType x);//尾插
void SLPopBack(SL* ps);//尾删

//头部操作
void SLPushFront(SL* ps, SLDateType x);//头插
void SLPopFront(SL* ps);//头删

//中间
size_t SLFind(SL* ps, SLDateType x);//查找(返回下标)
void SLInsert(SL* ps, size_t pos, SLDateType x);//在pos前插入数据x
void SLErase(SL* ps, size_t pos);//删除pos处的数据

void SLPrint(SL* ps);//打印顺序表

 

SeqList.c结构功能实现:

包含头文件#include"SeqList.h"

2.2.1顺序表的初始化

void SLInit(SL* ps)//顺序表的初始化
{
	assert(ps);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

 

2.2.2顺序表的销毁

💡ps:由于是动态开辟的空间,使用完要还给操作系统,不然会造成内存泄漏。

void SLDestroy(SL* ps)//顺序表的销毁
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

 

2.2.3尾插数据

void Enhance(SL* ps)
{
	size_t newcapacity = (ps->capacity == 0) ? 4 : ps->capacity * 2;//如果容量为0,开辟4,否则两倍开辟

	SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType)*newcapacity);//这里要考虑异地增容的情况
	if (tmp == NULL)//增容失败
	{
		perror("realloc fail\n");
		return;
	}
	else
	{
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

void SLPushBack(SL* ps, SLDateType x)//尾插
{
	assert(ps);//防止ps为空,进行断言

	//考虑增容
	if (ps->size == ps->capacity)//空间不足时需要增容
	{
		Enhance(ps);
	}

	ps->a[ps->size++] = x;
}

💡ps:顺序表插入操作都要检查是否需要增容

时间复杂度:O(1)

 

2.2.4尾删数据

void SLPopBack(SL* ps)//尾删
{
	assert(ps);

	assert(ps->size > 0);//顺序表为空,则不可继续再删除

	--(ps->size);
}

💡ps:顺序表的删除操作都要检查是是否为空顺序表

时间复杂度:O(1)

 

2.2.5头插数据

void SLPushFront(SL* ps, SLDateType x)//头插
{
	assert(ps);

	//考虑增容
	if (ps->size == ps->capacity)
	{
		Enhance(ps);
	}

	//挪动数据
	size_t end = ps->size;
	while (end > 0)
	{
		ps->a[end] = ps->a[end - 1];
		--end;
	}

	//插入数据
	ps->a[end] = x;
	++(ps->size);
}

💡ps:由于顺序表是连续存储的,在头部插入数据时,需要将整体数据向后挪动一次,再将数据插入到头部

在这里插入图片描述

时间复杂度:O(N)

 

2.2.6头删数据

void SLPopFront(SL* ps)//头删
{
	assert(ps);

	assert(ps->size > 0);

	//挪动数据
	--(ps->size);

	size_t begin = 0;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin + 1];
		++begin;
	}

}

💡ps:头删数据,将后面的数据向前移动,将第一个数据覆盖即可

在这里插入图片描述

时间复杂度:O(N)

 

2.2.7中间插入数据

void SLInsert(SL* ps, size_t pos, SLDateType x)//中间插
{
	assert(ps);

	assert(pos >= 0 && pos <= ps->size);//==0是头插,等于ps->size是尾插

	//考虑增容
	if (ps->size == ps->capacity)
	{
		Enhance(ps);
	}

    //挪动数据
    size_t cur = ps->size;
    while (cur > pos)
    {
        ps->a[cur] = ps->a[cur - 1];
        --cur;
    }


    //插入
    ps->a[cur] = x;
    ++(ps->size);

}

💡ps:中间插入数据,同样也需要向后挪动数据

时间复杂度:O(N)

 

2.2.8中间删除数据

void SLErase(SL* ps, size_t pos)//中间删
{
	assert(ps);

	assert(pos >= 0 && pos < ps->size);//等于0相等于头删,等于ps->size-1等于尾删

	//assert(ps->size > 0);//对pos的检查,间接检查了size要大于0

	--(ps->size);

	size_t cur = pos;
	while (cur < ps->size)
	{
		ps->a[cur] = ps->a[cur + 1];
		++cur;
	}
}

💡ps:中间删除数据,同样也需要向前挪动数据

时间复杂度:O(N)

 

2.2.9打印顺序表

void SLPrint(const SL* ps)//打印顺序表
{
	assert(ps);

	for (size_t i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

 

2.2.10查找数据

size_t SLFind(const SL* ps, SLDateType x)//查找(返回下标)
{
	assert(ps);

	for (size_t i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}

	return EOF;//找不到
}

 

2.2.11复用Insert和Erase实现尾部操作和头部操作

InsertErase功能中是包含了尾部操作和头部操作的,所以尾部操作和头部操作可以使用InsertErase来复用

void SLPushBack(SL* ps, SLDateType x)//尾插
{
	SLInsert(ps, ps->size, x);
}

void SLPopBack(SL* ps)//尾删
{
	SLErase(ps, ps->size - 1);
}

void SLPushFront(SL* ps, SLDateType x)//头插
{
	SLInsert(ps, 0, x);
}

void SLPopFront(SL* ps)//头删
{
	SLErase(ps, 0);
}

 

2.3顺序表的优缺点

优点:

1. 尾插和尾删的效率很高,时间复杂度为:O(1)
2. 支持随机访问,知道了一个元素的下标,就可以直接访问和修改

 

缺点:
1. 头部操作和中间操作中,需要挪动数据,时间复杂度为:O(N),效率较低
2. 增容会带来一定的性能消耗,特别是异地增容,代价是极大的
3. 2倍增容方式,会有一部分的空间浪费

 

3.顺序表OJ题目训练

  1. 原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。OJ链接
  2. 删除排序数组中的重复项。OJ链接
  3. 合并两个有序数组。OJ链接

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

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

相关文章

Linux学习第二十一节-sudo提权

1.概念 管理员提前为用户设置执行权限许可&#xff1b; 被授权用户有权执行授权命令&#xff1b; 配置文件&#xff1a;/etc/sudoers&#xff1b; 命令格式&#xff1a;sudo 特权命令。 2.提权操作 ①方式一vim编辑配置文件后wq&#xff01;&#xff1a;#vim /etc/sudo…

pnpm 基本详细使用(安装、卸载、使用)

一、简介 官网地址、GitHub地址、官方安装文档、官方卸载文档。 pnpm 全称 performant npm&#xff0c;意思为 高性能的 npm。pnpm 由 npm/yarn 衍生而来&#xff0c;解决了 npm/yarn 内部潜在的 bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景。被誉为 最先进的…

【Docker】之docker-compose的介绍与命令的使用

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录docker-compose简介docker-compose基础…

Word文档的密码忘记了怎么办?

Word文档可以设置两种密码&#xff0c;文件的“限制密码”和“打开密码”&#xff0c;今天来分享一下忘记这两种密码可以如何处理。 如果忘记的是Word文档的“限制密码”&#xff0c;文档就无法编辑及更改了&#xff0c;菜单目录中的相关选项也都是灰色状态&#xff0c;无法点…

LeetCode-343. 整数拆分

目录递归动态规划题目来源 343. 整数拆分 递归 对于给定的一个整数 n&#xff0c;穷举它的每一种分解情况&#xff0c;然后对所有情况&#xff0c;求最大值。 并且我们知道&#xff0c;n 可以拆成如下情况&#xff1a; 通过上图&#xff0c;我们很容易得到一个递归表达式&am…

Verilog使用always块实现时序逻辑

这篇文章将讨论 verilog 中一个重要的结构---- always 块&#xff08;always block&#xff09;。verilog 中可以实现的数字电路主要分为两类----组合逻辑电路和时序逻辑电路。与组合逻辑电路相反&#xff0c;时序电路电路使用时钟并一定需要触发器等存储元件。因此&#xff0c…

用Chrome浏览器加入新必应候补名单,微软最终还是无法赢得一切(~ ̄▽ ̄)~

前言 ChatGPT最近太火了&#xff0c;国内厂商刚开始宣布跟进时&#xff0c;微软必应搜索直接接入了ChatGPT的能力&#xff0c;推出了新必应。此举给Google当头一棒&#xff0c;相比于传统搜索引擎&#xff0c;新必应的这种搜索方式&#xff0c;让用户更快速的获取到自己问题的…

02 C语言计算

02 C语言计算 0、编程练习题 #include<stdio.h>int main(int argc,char const *argv[]){int a,b;scanf("%d %d",&a,&b);printf("%d %d %d\n",a,b,a b);printf("%d - %d %d\n",a,b,a - b);printf("%d * %d %d\n",a…

C/C++每日一练(20230305)

目录 1. 整数分解 ☆ 2. 二叉树的最小深度 ★★ 3. 找x ★★ 1. 整数分解 输入一个正整数&#xff0c;将其按7进制位分解为各乘式的累加和。 示例 1&#xff1a; 输入&#xff1a;49 输出&#xff1a;497^2示例 2&#xff1a; 输入&#xff1a;720 输出&#xff1a;720…

Java分布式事务(三)

文章目录&#x1f525;MySQL事务-MySQL中锁的分类&#x1f525;MySQL事务-MySQL中的死锁问题&#x1f525;MySQL事务-MySQL中锁的分类 MySQL中锁的分类 从本质上讲&#xff0c;锁是一种协调多个进程或多个线程对某一资源的访问的机制&#xff0c;MySQL使用锁和MVCC机制实现了…

TIA博途中将硬件目录更改为中文的具体方法演示

TIA博途中将硬件目录更改为中文的具体方法演示 基本步骤可参考如下: 第一步: 第二步: 具体的操作演示: 如下图所示,在所示的目录中找到zh-chs文件夹,删除或修改文件夹的名称均可,这里建议大家修改文件夹的名称,防止以后需要恢复成英文目录, 如下

3DEXPERIENCE Works 成为了中科赛凌实现科技克隆环境的催化剂

您的企业是否想过实现设计数据的统筹管理&#xff0c;在设计上实现标准化&#xff0c;并把每位设计工程师串联起来协同办公?中科赛凌通过使用3DEXPERIENCE Works 实现了上述内容&#xff0c;一起来看本期案例分享吧!中科赛凌 通过其自主研发的单压缩机制冷技术实现零下190℃制…

Hbase 的复制

HBase默认采用异步复制的方式同步数据&#xff0c;即客户端执行完put之后&#xff0c;RegionServer的后台线程不断地推送HLog的Entry到Peer集群。这种方式一般能满足大多数场景的需求&#xff0c;例如跨集群数据备份、HBase集群间数据迁移等。但是HBase 1.x版本的复制功能&…

【群晖Drive私有云】利用cpolar内网穿透实现公网远程群晖Drive

文章目录前言1.群晖Synology Drive套件的安装1.1安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用3. 结语前言 群晖作为专业的数据存储中心&#xff0…

路径规划 | 图解动态A*(D*)算法(附ROS C++/Python/Matlab仿真)

目录0 专栏介绍1 什么是D*算法&#xff1f;2 D*算法核心概念一览3 D*算法流程图4 步步图解&#xff1a;算法实例5 算法仿真与实现5.1 ROS C实现5.2 Python实现0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详…

【工具】logseq 使用分享

Github: https://github.com/logseq/logseq 三月八日国际劳动妇女节&#xff0c;当然要分享一款好用的记事本软件。 这次介绍的笔记本软件叫 logseq。 logseq 与传统的笔记软件不同&#xff0c;传统的笔记软件有各种数据单元&#xff08;post、title、refs、category、tags、…

智慧灌区信息化解决方案

系统概述智慧灌区信息化解决方案主要对对灌区的水情、雨情、土壤墒情、气象等信息进行监测&#xff0c;对重点区域进行视频监控&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;实现了信息的测量、统计、分析、控制、调度等功能。为灌区管理部门科学决策提供了依据&#…

VITA/PYTHON/LUPA families

Image Sensor Group Top to Bottom Portfolio in Industrial Imaging Machine Vision • Factory automation and inspection • Robotic vision • Biometrics High-End Surveillance • Aerial Surveillance • Intelligent Traffic Systems (ITS) • Mapping Medical and Sc…

【UML】软件需求说明书

目录&#x1f981; 故事的开端一. &#x1f981; 引言1.1编写目的1.2背景1.3定义1.4参考资料二. &#x1f981; 任务概述2.1目标2.2用户的特点2.3假定和约束三. &#x1f981; 需求规定3.1 功能性需求3.1.1系统用例图3.1.2用户登录用例3.1.3学员注册用例3.1.4 学员修改个人信息…

Uipath DataTable-FilterDataTable(筛选数据表)

FilterDataTable(筛选数据表) 活动描述 FilterDataTable(筛选数据表)&#xff1a;通过在“筛选器向导”窗口中指定条件来筛选“DataTable”数据表变量&#xff0c;可以根据在该向导中指定的逻辑条件保留或删除行或列。使用如下图&#xff1a; FilterDataTable(筛选数据表)属…