顺序表【数据结构】

news2024/9/26 3:24:51

文章目录

  • :star2:1. 顺序表概念
  • :star2:2. 框架
  • 3. 基本功能
    • 3.1 头文件
    • :star:3.2 初始化
    • :star:3.3 扩容
    • :star:3.4 打印
    • :star:3.5 尾插
    • :star:3.6 头插
    • :star:3.7 尾删
    • :star:3.8 头删
    • :star:3.9 指定插入
    • :star:3.10 指定删除
    • :star:3.11 查找
    • :star2:3.12 注意事项
  • 4. 顺序表的缺点

🌟1. 顺序表概念

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

将数据一个一个连续的存放在数组中,这种存储结构是顺序结构,采用顺序结构的线性表简称为顺序表
顺序表一般可以分为

  1. 静态顺序表 :使用定长数组存储数据
    在这里插入图片描述
  2. 动态顺序表(本章实现):动态开辟内存来存放数据
    在这里插入图片描述

🌟2. 框架

较大程序分3个及以上文件来写,这里分三个文件

  • SeqList.c
  • SeqList.h
  • Text.c

SeqList.c文件用来实现与顺序表有关的函数
SeqList.h文件用来声明函数和结构体
Text.c文件用来测试代码是否正确

3. 基本功能

顺序表需要实现的基本功能有

  • 头删
  • 尾删
  • 头插
  • 尾插
  • 随机删
  • 随机插
  • 查找
  • 打印
  1. 在正式实现顺序表功能之前,我们先对顺序表执行初始化,将顺序表的初始容量置为0,初始化函数SeqListInit
  2. 当我们插入数据时,需要检查Capacity是否满了,若满了,则需要扩容,扩容函数SeqListCheckCapacity

3.1 头文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLtype;
typedef struct
{
	SLtype* a;	//a是动态开辟的数组
	size_t size;	//有效数据的个数
	size_t capcity;//动态开辟数组的容量
}SeqList;

void SeqListInit(SeqList* ps);
//扩容
void SeqListCheckCapacity(SeqList* ps);
//打印
void SeqListPrint(SeqList* ps);
//尾插
void SeqListPushBack(SeqList* ps, SLtype pos);
//尾删
void SeqListPopBack(SeqList* ps);
//头插
void SeqListPushFront(SeqList* ps, SLtype pos);
//头删
void SeqListPopFront(SeqList* ps);
//随机插入
void SeqListInsert(SeqList* ps, int pos, SLtype data);
//随机删除
void SeqListDelecate(SeqList* ps, int pos);

以上函数的形参均是SeqList*类型的,因为我是将上述函数放在测试函数中进行测试,因此需要指针作为形式参数,如果形参是SeqList类型,则形参的改变不会影响实参,即顺序表的数据不会收到改变

⭐️3.2 初始化

初始化函数形参定义为顺序表类型的指针SeqList* ps

为了让顺序表类型SL变量有意义,先将SL的a成员赋值为NULL,capacity size成员赋值为0

void SeqListInit(SeqList* ps)
{
	ps->a = NULL;
	ps->capcity = ps->size = 0;

⭐️3.3 扩容

当容量满了后,顺序表选择将容量扩成原来最大容量的2倍,这样既不会浪费太多空间,也不会扩容太频繁,事实上,随着扩容的次数逐渐增多,一次扩容所产生的空间逐渐增加
扩容需要使用realloc函数
在这里插入图片描述
注:当memblock是NULL时,realloc会进行malloc的操作

void SeqListCheckcapacity(SeqList* ps)
{
	if (ps->size == ps->capacity) //有效数据的个数和最大容量相等时,需要扩容
	{
		ps->capacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//一开始将最大容量设置为4,后面扩成2倍
		ps->a = (SeqListDataType*)realloc(ps->a, sizeof(SeqListDataType) *  ps->capacity);
		assert(ps);
	}
}

⭐️3.4 打印

注意打印的个数是有效数据的个数,而不是最大容量

void SeqListPrint(SeqList* ps)
{
	for (int i = 0; i < ps->size; i++) //打印有效数据
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

⭐️3.5 尾插

因为size标记的就是顺序表的尾部,所以尾插较简单,只需要将a[size]赋值为插入的元素
在这里插入图片描述

void SeqListPushBack(SeqList* ps, int pos)
{

	//当顺序表的容量满了
	SeqListCheckcapacity(ps);
	ps->a[ps->size] = pos;
	ps->size++;//有效数据+1
}

⭐️3.6 头插

头插需要将所有的数据从前往后移动,并且保证挪动方向是[size-1]->[size],[size-2]->[size-1]……

void SeqListPushFront(SeqList* ps, int pos)
{
	SeqListCheckcapacity(ps);
	size_t cnt = 0;
	while (cnt < ps->size)//有多少个有效数据,移动多少次
	{
		ps->a[ps->size - cnt] = ps->a[ps->size - 1 - cnt];
		cnt++;
	}
	ps->a[0] = pos;
	ps->size++;
}

⭐️3.7 尾删

尾删很简单,只需要将有效数据的个数-1即可,即使该数据在动态开辟的数组中,但是不在有效数据范围内最后也不会打印

void SeqListPopBack(SeqList* ps)
{
	assert(ps->size);//注意当有效数据为0时不能够删数据
	ps->size--;
}

⭐️3.8 头删

头删和头差类似,都需要挪动其他的有效数据,头删时挪动方向是从后往前挪,并且保证最开始是[1]->[0],[2]->[1]……

void SeqListPopFront(SeqList* ps)
{
	assert(ps->size);
	size_t begin = 1;
	while (begin <= ps->size - 1)//size个有效数据移动size-1次
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

⭐️3.9 指定插入

有效数据元素为4时,插入到下标pos为2的位置,需要挪动数据3次
在这里插入图片描述
size越大,挪动的次数越多,pos越小,挪动的次数越多,因此在有效数据为size的数组中,将数据差到pos位置,需要挪动数据size-pos+1次,挪动方向[size-1]->[size],[size-2]->[size-1]……

void SeqListInsert(SeqList* ps, int pos, SeqListDataType data)
{
	assert(pos >= 1 && pos <= ps->capacity);//判断插入的位置是否合法
	SeqListCheckcapacity(ps);
	size_t cnt = 0;
	//一共循环size+1-pos次
	while (cnt < ps->size - pos + 1)
	{
		ps->a[ps->size - cnt] = ps->a[ps->size - 1 - cnt];
		cnt++;
	}
	ps->a[pos - 1] = data;
	ps->size++;//有效数据+1
}

⭐️3.10 指定删除

4个有效数据删除位置为2的元素需要挪动数据2次
在这里插入图片描述
推测size个有效数据删除位置为pos的元素需要挪动数据size-pos次,挪动方向[pos]->[pos-1],[pos+1]->[pos]……

void SeqListDelecate(SeqList* ps, int pos)
{
	assert(ps->size);
	assert(pos >= 0 && pos <= ps->size);
	//一共循环size-pos次
	while (pos < ps->size)
	{
		ps->a[pos - 1] = ps->a[pos];
		pos++;
	}
	ps->size--;
}

⭐️3.11 查找

查找很简单,直接遍历

void SeqListFind(SeqList* ps, int key)
{
	for (size_t i = 0; i < ps->size; i++)
	{
		if (key == ps->a[i])
		{
			printf("The pos is %d\n", i + 1);
			return;
		}
	}
	printf("Fail Find!\n");
}

🌟3.12 注意事项

  1. 凡是插入时,需要使用assert来判断插入位置是否合法
  2. 插入数据时,有效数据的个数需要+1,删除数据时,有效数据的个数需要-1

4. 顺序表的缺点

  1. 中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

针对顺序表的缺陷,我们研究出了链表,链表可以弥补顺序表得缺点,我们下次内容来研究如何实现链表

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

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

相关文章

云原生安全2.X 进化论系列|云原生安全2.X未来展望(4)

随着云计算技术的蓬勃发展&#xff0c;传统上云实践中的应用升级缓慢、架构臃肿、无法快速迭代等“痛点”日益明显。能够有效解决这些“痛点”的云原生技术正蓬勃发展&#xff0c;成为赋能业务创新的重要推动力&#xff0c;并已经应用到企业核心业务。然而&#xff0c;云原生技…

Git学习笔记(六)-标签管理

发布一个版本时&#xff0c;我们通常先在版本库中打一个标签&#xff08;tag&#xff09;&#xff0c;这样&#xff0c;就唯一确定了打标签时刻的版本。将来无论什么时候&#xff0c;取某个标签的版本&#xff0c;就是把那个打标签的时刻的历史版本取出来。所以&#xff0c;标签…

销售使用CRM系统集成Excel的五个技巧

销售过程中有很多情况会降低团队的效率。通过正确的实施CRM客户管理系统&#xff0c;可以帮助您的企业自动执行手动任务、减少错误并专注于完成交易。这里有5个技巧&#xff0c;可以帮助您的销售人员通过CRM集成Excel为销售流程赋能并提高他们的整体效率。 技巧1&#xff1a;将…

Python每日一练(20230309)

目录 1. 删除有序数组中的重复项 ★ 2. 二叉树的最小深度 ★★ 3. 只出现一次的数字 II ★★ &#x1f31f; 每日一练刷题专栏 C/C 每日一练 ​专栏 Python 每日一练 专栏 1. 删除有序数组中的重复项 给你一个有序数组 nums &#xff0c;请你原地删除重复出现的元素…

Xuetr杀毒工具使用实验(28)

实验目的 &#xff08;1&#xff09;学习Xuetr的基本功能&#xff1b; &#xff08;2&#xff09;掌握Xuetr的基本使用方法。预备知识 windows操作系统的基本知识如&#xff1a;进程、网络、服务和文件等的了解。 XueTr是近年推出的一款广受好评的ARK工具。ARK工具全称为Anti R…

Ubuntu20.04中Docker安装与配置

一、安装 1、卸载可能存在的旧版本 sudo apt-get remove docker docker-engine docker-ce docker.io2、更新apt包索引 sudo apt-get update显示“正在读取软件包列表… 完成” 3、安装以下包以使apt可以通过HTTPS使用存储库(repository) sudo apt-get install -y apt-tran…

java多线程(二三)并发编程:Callable、Future和FutureTask

一、Callable 与 Runnable 先说一下java.lang.Runnable吧&#xff0c;它是一个接口&#xff0c;在它里面只声明了一个run()方法&#xff1a; public interface Runnable {public abstract void run(); }由于run()方法返回值为void类型&#xff0c;所以在执行完任务之后无法返…

关于React Hook(18)

useState&#xff08;&#xff09;&#xff1a;&#x1f449;详情 &#xff08;必须“有条件地调用”&#xff1b;注意避免冗余状态的产生&#xff09; 关于useState的两种使用方式的区别&#xff1a;&#x1f449;详情 关于batch机制&#xff1a;有条件地调用一些状态的set方…

L3-021 神坛

在古老的迈瑞城&#xff0c;巍然屹立着 n 块神石。长老们商议&#xff0c;选取 3 块神石围成一个神坛。因为神坛的能量强度与它的面积成反比&#xff0c;因此神坛的面积越小越好。特殊地&#xff0c;如果有两块神石坐标相同&#xff0c;或者三块神石共线&#xff0c;神坛的面积…

STM32F103R8T6 SPWM实现正弦波输出

前言 PWM合成正弦波&#xff0c;原理什么的不详细说了&#xff0c;概括一下就是 PWM有效面积的积分 正弦波的有效面积。PWM的频率越快&#xff0c;细分的越多&#xff0c;锯齿也就越不明显。 做法是&#xff1a;首先利用正弦波取点软件&#xff0c;取点1000个&#xff0c;生…

计算机网络:OSPF协议和链路状态算法

OSPF协议 开放最短路经优先OSPF协议是基于最短路径算法SPF,其主要特征就是使用分布式的链路状态协议OSPF协议的特点&#xff1a; 1.使用泛洪法向自治系统中的所有路由器发送信息&#xff0c;即路由器通过输出端口向所有相邻的路由器发送信息&#xff0c;而每一个相邻的路由器又…

阶段二12_面向对象高级_继承3

知识点内容&#xff1a; 抽象类 模板设计模式 final关键字 一.抽象类 (1)抽象类概述 抽象方法&#xff1a;将共性的行为&#xff08;方法&#xff09;抽取到父类之后&#xff0c;发现该方法的实现逻辑 无法在父类中给出具体明确&#xff0c;该方法就可以定义为抽象方法。 抽…

ASP.NET CORE API 使用Orleans

快速使用Monimal API 快速集成Orleans 微软官网地址如下&#xff1a;https://learn.microsoft.com/zh-cn/dotnet/orleans/quickstarts/build-your-first-orleans-app?sourcerecommendations&tabsvisual-studio当然它的存储grain存储采用的是内存级别存储&#xff0c;我缓存…

JVM调优面试题——参数命令专题

文章目录1、JVM参数有哪些&#xff1f;1.1、 标准参数1.2、-X参数1.3、 -XX参数1.4、 其他参数1.5、 查看参数1.6、 设置参数的常见方式1.7、 常用参数含义2、JVM常用命令有哪些&#xff1f;2.1、jps2.2、jinfo2.3、jstat2.4、jstack2.5、jmap3、你会估算GC频率吗?4、 内存溢出…

【unity3D】创建TextMeshPro(TMP)中文字体(解决输入中文乱码问题)

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的TMP中文输入显示乱码的解决方式 创建 TextMeshPro 中文字体遇到的问题描述解决方式Font Asset Creator 面板扩展中文字体文本遇到…

深度学习零基础学习之路——第五章 个人数据集的制作

Python深度学习入门 第一章 Python深度学习入门之环境软件配置 第二章 Python深度学习入门之数据处理Dataset的使用 第三章 数据可视化TensorBoard和TochVision的使用 第四章 UNet-Family中Unet、Unet和Unet3的简介 第五章 个人数据集的制作 深度学习数据集的制作Python深度学…

MySQL 行锁

行锁 : 对表中行记录的锁 MySQL 的行锁 : 由各个引擎自己实现MyISAM 不支持行锁InnoDB 支持行锁 两阶段锁协议 : 行锁是在需要时才加上&#xff0c;要等到事务结束才释放 例子 : id 是表 t 的主键的 B 的 update 会阻塞&#xff0c;直到 A 执行 commit 后&#xff0c;B 才能…

Spring Cloud/Spring Cloud Alibaba核心知识总结

Spring Cloud核心知识总结 springCloud是一个服务治理平台&#xff0c;若干个框架的集合&#xff0c;提供了全套的分布式系统的解决方案。包含&#xff1a;服务注册与发现、配置中心、服务网关、智能路由、负载均衡、断路器、监控跟踪、分布式消息、分布式事务等等。 SpringC…

Python机器学习库scikit-learn在Anaconda中的配置

本文介绍在Anaconda环境中&#xff0c;安装Python语言scikit-learn模块的方法。 scikit-learn库&#xff08;简称sklearn&#xff09;是一个基于Python语言的机器学习库&#xff0c;提供了各种机器学习算法和相关工具&#xff0c;包括分类、回归、聚类、降维、模型选择和预处理…

TiDB Server

文章目录TiDB Server架构TiDB Server作用TiDB Server的进程SQL语句的解析和编译SQL读写相关模块在线DDL相关模块GC机制与相关模块TiDB Server的缓存热点小表缓存TiDB Server架构 Protocol Layer、Parse、Compile负责sql语句的解析编译和优化&#xff0c;然后生成sql语句执行计划…