数据结构第二讲:顺序表

news2024/11/27 5:32:45

数据结构第二讲:顺序表

  • 1.线性表
  • 2.什么是顺序表
  • 3. 静态顺序表
  • 4.动态顺序表
    • 4.1顺序表基础
    • 4.2顺序表的初始化
    • 4.3顺序表的销毁
    • 4.4顺序表的尾插
    • 4.5顺序表的头插
    • 4.6顺序表的尾删
    • 4.7顺序表的头删
    • 4.8顺序表在指定位置之前插入数据
    • 4.9顺序表删除指定位置的数据
    • 4.10顺序表查找数据
    • 4.11顺序表的打印
  • 5.算法题1
  • 6.算法题2
  • 7.算法题3
  • 8.顺序表问题以及思考

1.线性表

顺序表是数据结构中的一种组织方式,是N个具有相同特性数据元素的有限序列,常见的线性表有:顺序表、链表、栈、队列、字符串…
本篇博客我们将详细阐述顺序表的实现以及注意事项

线性表在逻辑上是线性的,在物理结构上不一定是连续的
而顺序表在逻辑上和物理结构上都是连续的

2.什么是顺序表

顺序表是用一段物理地址连续的存储单元存储数据元素的线性结构,一般情况下采用数组存储

顺序表的底层逻辑是数组,但是有不同于数组,顺序表是对数组进行封装,实现了常见的增删改查的接口,就像这样:
在这里插入图片描述

3. 静态顺序表

顺序表分为静态顺序表和动态顺序表两种,静态顺序表的实现如下:

//静态顺序表的实现
typedef int SLDateType;

#define N 100//数组长度

struct Seqlist
{
	SLDateType arr[N];//定长数组,用来存储数据

	int size;//有效数据个数
};

可以看出,静态顺序表中使用的是定长数组,它的大小是固定的,而动态属性表的大小是可变的,由此可见,动态顺序表要比静态顺序表好用一些

4.动态顺序表

4.1顺序表基础

完成顺序表之前,我们要先实现一个框架,这个框架由结构体来实现,具体如下:

//动态顺序表
typedef int SLDateType;

typedef struct SeqList
{
	SLDateType* a;//首先创建一个指针,指向动态开辟的地址
	int size;//有效数据的个数
	int capacity;//空间容量
}SL;

我们通过这个结构体创建了一个 sl 结构体变量

4.2顺序表的初始化

创建了一个变量,首先要做的就是对它的初始化,初始化很简单,操作如下:

//顺序表的初始化
void SLInit(SL* pa)
{
	//先将指向的空间赋值为0
	pa->a = NULL;
	//将大小全部初始化为0
	pa->capacity = 0;
	pa->size = 0;
}

4.3顺序表的销毁

写出了顺序表的初始化,我们顺便将顺序表的销毁也一并写了就行了,方式如下:

//顺序表的销毁
void SLDestory(SL* pa)
{
	//将结构体中的变量一一销毁即可
	if (pa->a != NULL)
	{
		free(pa->a);
		pa->a = NULL;
	}
	pa->capacity = 0;
	pa->size = 0;
}

4.4顺序表的尾插

在这里插入图片描述
既然size指向的位置就是需要插入的位置的下表,那么我们直接在size这个位置插入数据,然后将size++,指向下一个位置即可,操作方法如下:

//顺序表尾插
void SLPushBack(SL* ps, SLDateType x)
{
	if (ps->capacity == ps->size)
	{
		//首先判断一开始是否有空间
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;

		//然后需要开辟空间,才能插入数据
		SLDateType* pa = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));//此时一般开辟两倍的空间

		if (pa == NULL)
		{
			perror("realloc faile!");
			exit(-1);
		}
		ps->a = pa;
		ps->capacity = newcapacity;
	}

	//尾插就是直接将数据插入即可
	ps->a[ps->size++] = x;
}

在这串代码中,对于空间大小的判断需要经常使用,所以我们将它封装成一个函数即可:

//顺序表检查空间是否充足
void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		//首先判断一开始是否有空间
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;

		//然后需要开辟空间,才能插入数据
		SLDateType* pa = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));//此时一般开辟两倍的空间

		if (pa == NULL)
		{
			perror("realloc faile!");
			exit(-1);
		}
		ps->a = pa;
		ps->capacity = newcapacity;
	}
}

这时尾插就变得非常朴实无华了:

//顺序表尾插
void SLPushBack(SL* ps, SLDateType x)
{
	assert(ps);
	SLCheckCapacity(ps);

	//尾插就是直接将数据插入即可
	ps->a[ps->size++] = x;
}

4.5顺序表的头插

有尾插,那肯定要有头插,头插就是将所有数据向后移,然后在下标为0的位置插入数据即可:
平移前:
在这里插入图片描述
平移之后:
在这里插入图片描述
实现方法如下,一个简单的for循环即可:

//顺序表的头插
void SLPushFront(SL* ps, SLDateType x)
{
	//注意点:头插之前,需要判断ps是否为空
	assert(ps);

	//头插也一样,也需要先判断一下空间是否充足
	SLCheckCapacity(ps);

	//头插首先需要将所有数据进行后移
	for (int i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}

	//随后将数据插入到第一位即可
	ps->a[0] = x;
	ps->size++;
}

4.6顺序表的尾删

尾删非常简单,将size–就行了,因为根本就没有必要将数据删除!!!方法如下:

//顺序表的尾删
void SLPopBack(SL* ps)
{
	//首先需要先判断ps是否为空,没有空间不能删除,指针为空不能删除
	assert(ps);
	assert(ps->size);

	//直接将size-1就行了
	ps->size--;
}

4.7顺序表的头删

头删也很简单,将所有数据向前平移即可,将第一个数据覆盖掉就行了:

//顺序表的头删
void SLPopFront(SL* ps)
{
	//头删时,空指针不能删,没有空间不能删
	assert(ps);
	assert(ps->size);

	//头删将所有的数据向前平移,size--即可
	for (int i = 0; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

4.8顺序表在指定位置之前插入数据

随机插入数据才更显得高级,难道不是吗?
假设pos是我们需要插入位置的下标,方法根据画图来理解吧:
在这里插入图片描述
在这里插入图片描述
实现方法如下:

//顺序表在指定位置之前插入数据
void SLInsert(SL* ps, SLDateType x, int pos)
{
	//我们插入的位置肯定不能够超过有效空间的位置,也不能小于0
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	//先检查空间是否足够
	SLCheckCapacity(ps);

	//插入就是将数据进行后移,空出位置进行插入即可
	for (int i = ps->size; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[pos] = x;
	ps->size++;
}

4.9顺序表删除指定位置的数据

要删除指定位置的数据的话只需要一个平移就可以了,就是这样:
在这里插入图片描述
实现方法如下:

//顺序表删除指定位置的数据
void Erase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

4.10顺序表查找数据

查找数据十分简单,只需要遍历数组就可以了:

//顺序表查找数据
void SLFind(SL* ps, SLDateType x)
{
	assert(ps);

	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			printf("找到了! 下标为:%d\n", i);
			return;
		}
	}
	printf("没找到!\n");
}

4.11顺序表的打印

实现了那么多的操作,不打印一下看一下那怎么能行呢?打印很简单,方法如下:

//打印顺序表
void SLPrint(SL *ps)
{
	for (int i = 0; i < ps->size; i++)
		printf("%d ", ps->a[i]);
	printf("\n");
}

5.算法题1

链接: 移除元素

int removeElement(int* nums, int numsSize, int val) {
    int src = 0;
    int dst = 0;
    int k = numsSize;

    while (src < numsSize) {
        if (nums[src] == val) {
            src++;
            k--;
        } else
            nums[dst++] = nums[src++];
    }

    return k;
}

6.算法题2

链接: 删除有序数组中的重复项

int removeDuplicates(int* nums, int numsSize) {
    int src = 1;
    int dst = 0;
    int k = 1;

    while (src < numsSize) {
        if (nums[src] != nums[dst]) {
            nums[++dst] = nums[src];
            k++;
        }
        src++;
    }
    return k;
}

7.算法题3

链接: 合并两个有序数组

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int l1 = m - 1;
    int l2 = n - 1;
    int l3 = nums1Size - 1;

    while (1) {
        if (l3 == l1)
            return;
        if (l3 == l2)
            break;
            
        if (nums1[l1] > nums2[l2]) {
            nums1[l3--] = nums1[l1--];
        } else {
            nums1[l3--] = nums2[l2--];
        }
    }

    for (int i = l2; i >= 0; i--)
        nums1[i] = nums2[i];
}

8.顺序表问题以及思考

当然,顺序表并不是完美的,它仍然具有着一些问题:
在这里插入图片描述
为了解决以上问题,我们就需要引入一个东西:链表,这个我们下一次再讲!!!

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

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

相关文章

ubuntu22.04 安装 NVIDIA 驱动以及CUDA

目录 1、事前问题解决 2、安装 nvidia 驱动 3、卸载 nvidia 驱动方法 4、安装 CUDA 5、安装 Anaconda 6、安装 PyTorch 1、事前问题解决 在安装完ubuntu之后&#xff0c;如果进入ubuntu出现黑屏情况&#xff0c;一般就是nvidia驱动与linux自带的不兼容&#xff0c;可以通…

AMQP-核心概念-4

本文参考以下链接摘录翻译&#xff1a; https://www.rabbitmq.com/tutorials/amqp-concepts 绑定 (Bindings) 绑定是交换机用来将消息路由到队列的规则。为了让一个交换机E将消息路由到队列Q&#xff0c;Q必须绑定到E。绑定可以有一个可选属性routing key&#xff0c;有一些类…

uart开发调试

1. Uart基本框架 1.1概念 通信系统有两种方式&#xff0c;同步通信和异步通信. 同步通信的典型特征&#xff1a;通信双方公用同一个时钟&#xff0c;发送/接受速率完全一致&#xff0c;通信时需要带时钟信号传输. 异步通信的典型特征&#xff1a;通信双方各自具有独立的时钟…

电脑为什么会出现“找不到msvcr120.dll无法执行代码”?如何解决msvcr120.dll丢失错误

在使用电脑的过程中不知带大家有没有遇到过“找不到msvcr120.dll无法执行代码”的错误提示的情况&#xff0c;出现这样的情况大家都有什么解决办法可以解决&#xff1f;有什么办法能够帮助大家修复丢失的msvcr120.dll文件。接下来这篇文章就将教大家修复“找不到msvcr120.dll无…

Vue3-拉开序幕的setup

Vue3 中的 setup 是一个新的配置项&#xff0c;值是一个函数。 export default {name: App,setup: function () {} } </script> 和 Vue2 中的 data 一样&#xff0c;我也可以将 setup 简写成为 export default {name: App,setup() {} } setup函数的使用 与 Vue2 不一样…

刷题计划 day4 【双指针、快慢指针、环形链表】链表下

⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题&#xff0c;往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题…

十一、【Python】基础教程-【Python全掌握】六大基础数据类型:布尔类型的终极指南

目录 一、基础类型“布尔型”处理方法 1. 直接赋值和使用 2. 布尔值的逻辑运算 3. 条件语句中的布尔值 4. 布尔值转换 5. 短路逻辑 6. 在循环和迭代中的使用 一、基础类型“布尔型”处理方法 在Python中&#xff0c;布尔类型是一种基本的数据类型&#xff0c;用于表示逻…

MySQL 索引相关基本概念

文章目录 前言一. B Tree 索引1. 概念2. 聚集索引/聚簇索引3. 辅助索引/二级索引4. 回表5. 联合索引/复合索引6. 覆盖索引 二. 哈希索引三. 全文索引 前言 InnoDB存储引擎支持以下几种常见索引&#xff1a;BTree索引&#xff0c;哈希索引&#xff0c;全文索引 一. B Tree 索引…

1、hadoop环境搭建

1、环境配置 ip(/etc/sysconfig/network-scripts) # 网卡1 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOstatic IPADDR192.168.59.11 GATEWAY192.168.59.1 NETMASK 255.255.255.0 # 网卡2 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOdh…

均匀圆形阵列原理及MATLAB仿真

均匀圆形阵列原理及MATLAB仿真 目录 前言 一、均匀圆阵原理 二、圆心不存在阵元方向图仿真 三、圆心存在阵元方向图仿真 四、MATLAB仿真代码 总结 前言 本文详细推导了均匀圆形阵列的方向图函数&#xff0c;对圆心不放置阵元和圆心放置阵元的均匀圆形阵列方向图都进行了仿…

前端JS特效第57波:响应式博客网站图文幻灯片

响应式博客网站图文幻灯片&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下&#xff1a; <!DOCTYPE html> <html lang"zh-CN"><head> <meta charset"utf-8"> <title>响应式博客幻灯片演示</title><link …

pyuic5将ui文件转换为py文件报错:one input ui-file must be specified;no element found;

ERROR 1 文件命名不规范Solution 1:文件命名不能有空格 ERROR 2未选中ui文件 Solution 2:选中要转换成py 的文件

深入解析:百数平台图表联动功能设置与实战应用

在当今数据驱动的时代&#xff0c;图表的联动功能已成为数据分析的得力助手。通过深度整合各类图表&#xff0c;如柱形图、折线图、饼图、雷达图、条形图、透视图、面积图、双轴图、地图以及漏斗图等&#xff0c;我们实现了图表之间的无缝衔接&#xff0c;使得数据的呈现与探索…

基于FFmpeg和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

RFID标签打印机助力服装厂实现智能化管理

随着服装行业的快速发展&#xff0c;传统的管理模式已无法满足现代化生产的需求。RFID技术作为一种先进的自动识别技术&#xff0c;正在改变服装厂的管理方式。常达智能物联致力于为客户提供高效的RFID解决方案&#xff0c;其中RFID标签打印机在服装厂的应用尤为重要。本文将探…

IDEA-安装插件 驼峰下划线转换

第一步&#xff1a;安装 file-settings-plugins-在marketplace搜索“CamelCase”-点击安装 第二步&#xff1a;设置 file-settings-editor-camel_case 第三步&#xff1a;使用 选中想转换的遍历 使用快捷键 Alt Shift U

【算法专题】双指针算法之LCR 179. 查找总价格为目标值的两个商品(力扣)

欢迎来到 CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;双指针算法之LCR 179. 查找总价格为目标值的两个商品&#xff08;力扣&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法…

C++学习笔记——模板

学习视频 文章目录 模板的概念函数模板函数模板语法函数模板注意事项函数模板案例普通函数与函数模板的区别普通函数与函数模板的调用规则模板的局限性 类模板类模板与函数模板区别类模板中成员函数创建时机类模板对象做函数参数类模板与继承类模板成员函数类外实现类模板分文件…

2024年钉钉杯大数据竞赛A题超详细解题思路+python代码手把手保姆级运行讲解视频+问题一代码分享

初赛A&#xff1a;烟草营销案例数据分析 AB题综合难度不大&#xff0c;难度可以视作0.4个国赛&#xff0c;题量可以看作0.35个国赛题量。适合于国赛前队伍练手&#xff0c;队伍内磨合。竞赛获奖率50%&#xff0c;八月底出成绩&#xff0c;参赛人数3000队左右。本文将为大家进行…

docker安装部署elasticsearch7.15.2

docker安装部署elasticsearch7.15.2 1.拉取es镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.2如果不想下载或者镜像拉去太慢可以直接下载文章上面的镜像压缩包 使用镜像解压命令 docker load -i elasticsearch-7-15-2.tar如下图所示就表示镜像解压成…