数据结构--顺序表(图文)

顺序表的概念和特点

顺序表是一种线性数据结构,它由一组数据元素构成,这些元素具有相同的特性,并按照一定的顺序排列。在顺序表中,数据元素通常存储在连续的内存空间中,这使得通过索引可以直接访问到表中的任意元素。

顺序表的特点如下:

  1. 连续的存储空间:顺序表中的元素在内存中占据一段连续的空间,这使得访问任何一个元素的时间复杂度都为O(1),即访问速度快。

  2. 动态性:顺序表可以是静态的,也可以是动态的。静态顺序表一旦初始化后,其空间大小就不能更改;而动态顺序表则可以根据需要动态地调整空间大小,即在空间不足时可以自动扩容,空间过多时可以缩容。

  3. 随机访问:由于元素存储是连续的,顺序表支持随机访问,即可以直接通过索引来访问元素,这一点与链表不同,链表需要遍历才能访问到指定位置的元素。

  4. 插入和删除操作:顺序表的插入和删除操作可能需要移动大量的元素,尤其是在插入或删除中间的元素时,时间复杂度为O(N),其中N是表中元素的数量。因此,顺序表在执行插入和删除操作时效率较低,这是它的一个缺点。

  5. 内存预分配与动态调整:在动态顺序表中,内存可以根据需要预先分配或动态调整。预分配指的是在创建顺序表时指定一个初始大小,后续根据实际情况可能进行扩容;动态调整则是在运行时根据需要增大或减小内存空间。

顺序表的实现

对比静态顺序表,动态顺序表更有优势,同样在项目中,动态顺序表的应用远远大于静态顺序表,下面我们就来实现动态顺序表。
首先创建三个文件:

  • SeqList.h —— 用于声明函数的头文件
  • SeqList.c —— 顺序表主要函数的实现
  • test.c——>测试顺序表。

创建顺序表

typedef int SLDataType;//方便后续使用更改类型
typedef struct SeqList
{SLDataType* arr;//数组指针int size;//记录当前有效的数组大小int capacity;//记录当前总空间大小
}SL;

对顺序表初始化

void InitSeqList(SL* ps)//初始化顺序表
{ps->arr = NULL;ps->capacity = ps->size = 0;
}

顺序表的销毁

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

打印顺序表

void SLPrint(const SL* ps)//打印顺序表的数据
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size; i++){printf("%d", ps->arr[i]);}
}

在给数据表增加数据前,我们先封装一个函数,用来判断顺序表是否已满,如果满则需要开辟新空间。

判断扩容

void SLCheckCapacity(SL* ps)//判断是否需要增容
{assert(ps);if (ps->capacity == ps->size)//数组已满{int newcapacity = (ps->capacity == 0) ? 4 : 2 * ps->capacity;//如果空间为0则开辟4个空间,否则开辟原空间二倍SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}}

头插

在这里插入图片描述

void SLPushFront(SL* ps, SLDataType x)//在顺序表的头部插入数据
{assert(ps);SLCheckCapacity(ps);//判断是否需要扩容,如需要则扩容for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}

尾插

void SLPushBack(SL* ps, SLDataType x)//在顺序表的末尾插入数据
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}

指定位置插入

在这里插入图片描述

void SLInsert(SL* ps, int pos, SLDataType x)//在指定位置插入数据
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

头删

在这里插入图片描述

void SLPopFront(SL* ps)//删除顺序表头部的数据
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

尾删

直接size–就可以了

void SLPopBack(SL* ps)//删除顺序表尾部的数据
{assert(ps);assert(ps->size);ps->size--;
}

删除指定位置

在这里插入图片描述

void SLErase(SL* ps, int pos)//删除指定位置的数据
{assert(ps);assert(ps->size);for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

查找数据

直接遍历数组找相等

int SLFind(SL* ps, SLDataType x)//在顺序表中查找数据,返回数组下标,没找到返回-1
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;//找到了,返回x在顺序表中的下标}}return -1;//没找到
}

顺序表源码

SeqList.c

#pragma once
#include"SeqList.h"void InitSeqList(SL* ps)//初始化顺序表
{ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLDestroy(SL* ps)//销毁顺序表
{free(ps->arr);ps->arr = NULL;ps->capacity = ps->size = 0;
}
void SLPrint(const SL* ps)//打印顺序表的数据
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size; i++){printf("%d", ps->arr[i]);}
}void SLCheckCapacity(SL* ps)//判断是否需要增容
{assert(ps);if (ps->capacity == ps->size){int newcapacity = (ps->capacity == 0) ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}}
void SLPushFront(SL* ps, SLDataType x)//在顺序表的头部插入数据
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}
void SLPushBack(SL* ps, SLDataType x)//在顺序表的末尾插入数据
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}
void SLInsert(SL* ps, int pos, SLDataType x)//在指定位置插入数据
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
void SLPopFront(SL* ps)//删除顺序表头部的数据
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
void SLPopBack(SL* ps)//删除顺序表尾部的数据
{assert(ps);assert(ps->size);ps->size--;
}
void SLErase(SL* ps, int pos)//删除指定位置的数据
{assert(ps);assert(ps->size);for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
int SLFind(SL* ps, SLDataType x)//在顺序表中查找数据,返回数组下标,没找到返回-1
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;//找到了,返回x在顺序表中的下标}}return -1;//没找到}

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;//方便后续使用更改类型typedef struct SeqList
{SLDataType* arr;//数组指针int size;//记录当前有效的数组大小int capacity;//记录当前总空间大小
}SL;void InitSeqList(SL* ps);//初始化顺序表void SLDestroy(SL* ps);//销毁顺序表void SLPrint(const SL* ps);//打印顺序表的数据void SLPushFront(SL* ps, SLDataType x);//在顺序表的头部插入数据void SLPushBack(SL* ps, SLDataType x);//在顺序表的末尾插入数据void SLInsert(SL* ps, int pos, SLDataType x);//在指定位置插入数据void SLPopFront(SL* ps);//删除顺序表头部的数据void SLPopBack(SL* ps);//删除顺序表尾部的数据void SLErase(SL* ps, int pos);//删除指定位置的数据int SLFind(SL* ps, SLDataType x);//在顺序表中查找数据,返回数组下标,没找到返回-1

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

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

相关文章

tiaoshixitong

data_interval : 当是ubus 时 重新赋值为 3&#xff1b;当是ws 时 重新赋值为 20&#xff1b; 1. 如何理解data_tik &#xff1f; 在函数can_packet_check_timer 定时can发送函数里面&#xff0c;data_tik 作为倒计时时间&#xff0c;当倒计时间到&#xff0c;则发送。…

Nuxt3页面开发实战探索

title: Nuxt3页面开发实战探索 date: 2024/6/19 updated: 2024/6/19 author: cmdragon excerpt: 摘要&#xff1a;这篇文章是关于Nuxt3页面开发实战探索的。它介绍了Nuxt3的基础入门&#xff0c;安装与配置&#xff0c;项目结构&#xff0c;内置组件与功能&#xff0c;以及页…

Maven 的生命周期详解

Maven 是目前最流行的项目管理和构建工具之一&#xff0c;广泛应用于 Java 开发项目中。它通过一系列约定和配置&#xff0c;极大地简化了项目的构建、依赖管理和生命周期管理。其中&#xff0c;Maven 的生命周期是其核心概念之一&#xff0c;贯穿了项目从构建、测试、打包到部…

笔记本Win + v剪贴板打开失效问题解决

使用快捷键winv打开剪贴板时&#xff0c;突然没有了反应&#xff0c;原因是explorer.exe程序占用了winv键。解决方法&#xff1a; 1、管理员身份运行powershell 2、先杀掉explorer.exe程序&#xff1a;taskkill /f /im explorer.exe 3、重启explorer.exe程序 4、再使用winv …

Mybatis快速批量插入10万条数据实战

使用Mybatis大概有以下4种常见插入方法 1.使用for循环&#xff0c;每次执行一次insert插入(效率低不推荐) 2.使用MyBatis的标签遍历插入(效率低不推荐) 3.使用Mybatis&#xff0c;纯sql插入(推荐,效率最高) 4.使用 SqlSessionFactory&#xff0c;每一批数据执行一次提交(重点推…

变声方法大公开,变女声很自然的3款变声器推荐,值得收藏

将男声变成女声并且要很自然的变声器有吗&#xff1f;很多喜欢玩游戏的小伙伴们在进行游戏连麦时&#xff0c;可能为了增加趣味&#xff0c;想要试试变成女声来交流&#xff0c;或者喜欢视频剪辑创作的小伙伴们在进行视频配音时&#xff0c;不想用自己的声音出镜&#xff0c;需…

市值飙升!超微软、苹果,英伟达成为全球市值最高上市公司

KlipC报道&#xff1a;当地时间6月18日&#xff0c;英伟达股价再度大涨&#xff0c;盘后股价上涨3.51%&#xff0c;总市值达3.335万亿美元&#xff0c;报135.58美元再刷历史新高&#xff0c;超微软、苹果成为全球市值最高的上市公司。 值得一提的是&#xff0c;在本月初&#x…

vue3面试题八股集合——2024

vue3比vue2有什么优势&#xff1f; 性能更好&#xff0c;打包体积更小&#xff0c;更好的ts支持&#xff0c;更好的代码组织&#xff0c;更好的逻辑抽离&#xff0c;更多的新功能 描述Vu3生命周期 Options API的生命周期&#xff1a; beforeCreate: 在实例初始化之后、数据观…

深入理解AQS:Java并发编程中的核心组件

目录 AQS简介AQS的设计思路AQS的核心组成部分 状态&#xff08;State&#xff09;同步队列&#xff08;Sync Queue&#xff09;条件队列&#xff08;Condition Queue&#xff09; AQS的内部实现 节点&#xff08;Node&#xff09;锁的获取与释放 独占锁共享锁 条件变量 AQS的应…

Linux top 命令使用教程

转载请标明出处&#xff1a;https://blog.csdn.net/donkor_/article/details/139775547 文章目录 一、top 是什么二、top的基础语法三、top输出信息解读 一、top 是什么 Linux top 是一个在Linux和其他类 Unix 系统上常用的实时系统监控工具。它提供了一个动态的、交互式的实时…

数据库系统

数据库系统概论 数据库系统概论是一门研究如何设计、实现、管理和维护数据库的学科&#xff0c;它是计算机科学的重要分支&#xff0c;主要关注数据的组织、存储和处理。数据库系统的核心组成部分包括以下几个方面&#xff1a; 数据库&#xff08;Database&#xff09;&#…

云计算【第一阶段(16)】安装及管理程序

目录 一、linux 应用程序基础 1.1、应用程序与系统命令的关系 1.2、典型应用程序的目录结构 1.3、常见的软件包封装类型 二、RPM软件包管理工具 2.1、rpm命令的格式 2.2、安装&#xff0c;升级&#xff0c;卸载 rpm软件包 安装软件包 升级软件包 卸载软件包 查询软件…

Python 学习 第三册 第10章 一些简单的算法

---用教授的方式学习。 目录 10.1 搜索算法 10.1.1 线性搜索与间接引用元素 10.1.2 二分查找和利用假设 10.2 排序算法 10.2.1 归并排序 10.2.2 将函数用作参数 10.3 散列表 10.1 搜索算法 本节会研究两种搜索列表的算法,每种方法都满足以下规范: def search(L, e)…

Android OTA 升级基础知识详解+源码分析

前言&#xff1a; 本文仅仅对OTA升级的几种方式的概念和运用进行总结&#xff0c;仅在使用层面对其解释。需要更详细的内容我推荐大神做的全网最详细的讲解&#xff1a; https://blog.csdn.net/guyongqiangx/article/details/129019303?spm1001.2014.3001.5502 三种升级方式…

前端高级架构师课程(总共111门课程,1150GB)

由阿里P8前端架构师亲自精心筛选整理的全网最新最具价值的前端进阶学习课程&#xff01; 培训机构原版教程&#xff01; 课程知识点和一线大厂完美匹配&#xff01; 所有课程资源完整成套&#xff0c;不残缺&#xff0c;不拼凑&#xff0c;不拆开乱发&#xff01; 这系列课程包…

JavaScript-拓展简单和引用数据类型

学习目标&#xff1a; 掌握拓展简单和引用数据类型 学习内容&#xff1a; 拓展-术语解释拓展-基本数据类型和引用数据类型 拓展-术语解释&#xff1a; 拓展-基本数据类型和引用数据类型&#xff1a; 简单类型又叫做基本数据类型或者值类型&#xff0c;复杂类型又叫做引用类型…

第一百一十一节 Java面向对象设计 - Java泛型方法和构造函数

Java面向对象设计 - Java泛型方法和构造函数 泛型方法 我们可以在方法声明中定义类型参数&#xff0c;它们在方法的返回类型之前的尖括号中指定。 包含泛型方法声明的类型不必是泛型类型。 我们可以在非静态方法声明中使用为泛型类型指定的类型参数。 例子 以下代码显示如…

如何快速在一台新电脑上安装 Python 环境

一、下载miniconda 1.下载 我们可以在清华大学开源软件镜像站下载最新版本的miniconda。如&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py38_4.9.2-Windows-x86_64.exe 2.安装 双击exe文件安装&#xff0c;如果没有特殊的需求&#x…

UML详解

1.what is the UML UML 全称是 Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;它以图形的方式来描述软件的概念 2.它存在的目的 UML 的目标是通过一定结构的表达&#xff0c;来解决现实世界到软件世界的沟通问题。 3.什么是模&#xff0c;…

127.0.0.1与本机IP地址的区别

大家好&#xff0c;今天我们来聊聊一个在网络世界中常常被提及&#xff0c;但可能对于非专业人士来说还有些模糊的概念——127.0.0.1与本机IP地址。这两个地址在网络通信中都扮演着重要的角色&#xff0c;但它们之间又有着怎样的区别呢&#xff1f;让我们一起来探究一下。 一、…