数据结构·一篇搞定顺序表!

news2025/5/24 23:01:06

大家好啊,几日不见,甚是想念,从这一篇文章开始,我们就要进入数据结构了哦,那么我们废话不多说,今天我们一起来搞定顺序表!!!
请添加图片描述

1. 顺序表概念及结构

顺序表是一种线性结构,它由一组连续的存储单元(通常是数组)组成,数据元素之间的关系是相邻的。顺序表中的元素是按照一定的顺序排列的,可以通过下标来访问和操作各个元素。顺序表的结构简单、易于实现,是一种常见的数据结构之一。

2. 顺序表分类

• 顺序表和数组的区别
◦ 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接口

静态顺序表

#define MAX_SIZE 10

typedef struct {
    int data[MAX_SIZE];
    int length;
} StaticList;

在这个例子中,我们定义了一个包含10个整数元素的静态顺序表,其中data数组存储元素,length表示当前顺序表中元素的个数。在使用静态顺序表时,需要注意不要超出预先定义的最大长度,否则可能导致数组越界错误.

动态顺序表

在这里插入图片描述
我们一般使用顺序表都是动态顺序表,这样的话才可以进行增删改查的操作,那么我们接下来就来康康这些操作~

3. 实现动态顺序表

#define INIT_CAPACITY 4
typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
 SLDataType* a;
 int size; // 有效数据个数
 int capacity; // 空间容量
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插⼊删除 / 尾部插⼊删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);
//指定位置之前插⼊/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

下面是实现的代码

#define INIT_CAPACITY 4  
  
typedef int SLDataType;  
  
typedef struct SeqList {  
    SLDataType* a;  
    int size; // 有效数据个数  
    int capacity; // 空间容量  
} SL;  

3.1 初始化

// 初始化  
void SLInit(SL* ps) {  
    ps->a = (SLDataType*)malloc(INIT_CAPACITY * sizeof(SLDataType));  
    if (!ps->a) {  
        exit(EXIT_FAILURE); // 分配内存失败  
    }  
    ps->size = 0;  
    ps->capacity = INIT_CAPACITY;  
}  
  1. 通过 malloc 函数为顺序线性表的数组成员 a 分配内存空间,大小为 INIT_CAPACITY *
    sizeof(SLDataType),其中 INIT_CAPACITY 是一个预先定义的常量,表示初始容量。
  2. 检查内存分配是否成功,如果分配失败(即 ps->a 为 NULL),则调用 exit(EXIT_FAILURE)
    函数退出程序。
  3. 将顺序线性表的 size 成员初始化为 0,表示当前表中没有元素。
  4. 将顺序线性表的 capacity 成员初始化为INIT_CAPACITY,表示表的初始容量为 INIT_CAPACITY。

3.2 销毁

void SLDestroy(SL* ps) {  
    free(ps->a);  
    ps->a = NULL;  
    ps->size = 0;  
    ps->capacity = 0;  
}  
  1. 调用 free 函数释放顺序线性表的数组成员 a 所占用的内存空间,这样可以避免内存泄漏。
  2. 将顺序线性表的 a 成员指针设置为 NULL,这是一种良好的习惯,可以避免出现野指针访问的问题。
  3. 将顺序线性表的 size 成员设为 0,表示表中不再有元素。
  4. 将顺序线性表的 capacity 成员设为 0,表示表的容量为 0。

3.3 打印

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

这个没什么好说的吧哈哈哈

3.4 扩容

void SLCheckCapacity(SL* ps) {  
    if (ps->size == ps->capacity) {  
        ps->capacity *= 2;  
        SLDataType* temp = (SLDataType*)realloc(ps->a, ps->capacity * sizeof(SLDataType));  
        if (!temp) {  
            exit(EXIT_FAILURE); // 扩容失败  
        }  
        ps->a = temp;  
    }  
}  
  1. 判断顺序线性表的当前大小(size)是否等于容量(capacity),如果相等,则表示表中元素已经填满,需要进行扩容操作。
  2. 将顺序线性表的容量 capacity 扩大为原来的两倍,即 ps->capacity *= 2;,这里采用了简单的扩容策略。
  3. 调用 realloc 函数重新分配内存空间,将原来的数据拷贝到新的空间中,大小为 ps->capacity *
    sizeof(SLDataType)。
  4. 检查是否成功分配新的内存空间,如果分配失败(即 temp 为 NULL),则调用 exit(EXIT_FAILURE)
    函数退出程序。
  5. 将新分配的内存空间的地址赋值给顺序线性表的数组成员 a,完成扩容操作。

3.5 头部插入

void SLPushFront(SL* ps, SLDataType x) {  
    SLCheckCapacity(ps);  
    for (int i = ps->size; i > 0; i--) {  
        ps->a[i] = ps->a[i - 1];  
    }  
    ps->a[0] = x;  
    ps->size++;  
}  
  1. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  2. 从顺序线性表的最后一个元素开始,依次将元素向后移动一个位置,为新元素腾出空间。这里使用循环从 ps->size
    开始,依次向前移动元素,直到第一个元素。
  3. 将要插入的新元素 x 放入顺序线性表的第一个位置,即头部位置。
  4. 增加顺序线性表的大小 size,表示表中元素数量增加了一个。

3.6 头部删除

void SLPopFront(SL* ps) {  
    if (ps->size == 0) {  
        return;  
    }  
    for (int i = 0; i < ps->size - 1; i++) {  
        ps->a[i] = ps->a[i + 1];  
    }  
    ps->size--;  
}  
  1. 判断顺序线性表的大小(size)是否为0,如果是空表(size == 0),则直接返回,不进行删除操作。
  2. 从顺序线性表的第一个元素开始,依次将元素向前移动一个位置,覆盖掉原来的元素。这里使用循环从0开始,依次向后移动元素,直到倒数第二个元素。
  3. 减少顺序线性表的大小 size,表示表中元素数量减少了一个。

3.7 尾部插入

void SLPushBack(SL* ps, SLDataType x) {  
    SLCheckCapacity(ps);  
    ps->a[ps->size] = x;  
    ps->size++;  
}  
  1. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  2. 将要插入的新元素 x 放入顺序线性表当前大小(size)的位置,即在尾部插入。
  3. 增加顺序线性表的大小 size,表示表中元素数量增加了一个。

3.8 尾部删除

不用说吧~~~

void SLPopBack(SL* ps) {  
    if (ps->size == 0) {  
        return;  
    }  
    ps->size--;  
}  

3.9 指定位置之前插入数据

void SLInsert(SL* ps, int pos, SLDataType x) {  
    if (pos < 0 || pos > ps->size) {  
        return; // 插入位置不合理  
    }  
    SLCheckCapacity(ps);  
    for (int i = ps->size; i > pos; i--) {  
        ps->a[i] = ps->a[i - 1];  
    }  
    ps->a[pos] = x;  
    ps->size++;  
}  
  1. 判断插入位置 pos 是否合理,即必须满足 pos >= 0 且 pos <= ps->size,否则直接返回,不进行插入操作。
  2. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  3. 从顺序线性表的最后一个元素开始,依次将元素向后移动一个位置,为新元素腾出空间。这里使用循环从 ps->size开始,依次向前移动元素,直到插入位置 pos。
  4. 将要插入的新元素 x 放入顺序线性表的指定位置 pos。
  5. 增加顺序线性表的大小 size,表示表中元素数量增加了一个.

3.10 指定位置删除数据

void SLErase(SL* ps, int pos) {  
    if (pos < 0 || pos >= ps->size) {  
        return; // 删除位置不合理  
    }  
    for (int i = pos; i < ps->size - 1; i++) {  
        ps->a[i] = ps->a[i + 1];  
    }  
    ps->size--;  
}  
  1. 判断删除位置 pos 是否合理,即必须满足 pos >= 0 且 pos < ps->size,否则直接返回,不进行删除操作。
  2. 从指定位置 pos 开始,将后面的元素依次向前移动一个位置,覆盖掉要删除的元素。这里使用循环从 pos
    开始,依次将元素向前移动,直到倒数第二个元素。
  3. 减少顺序线性表的大小 size,表示表中元素数量减少了一个,相当于删除了一个元素。

3.11 查找数据

int SLFind(SL* ps, SLDataType x) {  
    for (int i = 0; i < ps->size; i++) {  
        if (ps->a[i] == x) {  
            return i; // 返回数据下标  
        }  
    }  
    return -1; // 没有找到数据  
}  

4. 基于动态顺序表实现通讯录项目

相信大家掌握了上面的操作后,实现通讯录并不是啥难事,肖恩在这也不细细讲解了,希望大家理解哦~~~请添加图片描述

由于这个通讯录的代码有一点点多,放在这里大家也不好学习,我直接放个链接吧,大家直接点开就欧克了,也方便copy.
通讯录

5. 顺序表经典算法

这是两个有关顺序表的经典的算法的,大家点开链接可以做做,同样,我把代码放在这,大家自行悟道
经典算法OJ题1: 移除元素

int removeElement(int* nums, int numsSize, int val) {
        int i, j;
    for(i = 0, j = 0; i < numsSize; i++){
        if(nums[i] != val){
            nums[j] = nums[i];
            j++;
        }
    }
    return j;
}

经典算法OJ题2: 合并两个有序数组

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
int p1 = m - 1;
    int p2 = n - 1;
    int p = m + n - 1;
    
    while(p1 >= 0 && p2 >= 0){
        if(nums1[p1] > nums2[p2]){
            nums1[p] = nums1[p1];
            p1--;
        } else {
            nums1[p] = nums2[p2];
            p2--;
        }
        p--;
    }
    
    while(p2 >= 0){
        nums1[p] = nums2[p2];
        p2--;
        p--;
    }
}

大家要是有比这个好的方法那就更好了!还是比肖恩强的哈哈哈

6. 顺序表的问题及思考*

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

思考:如何解决以上问题呢?

在这里插入图片描述
下期预告
那当然是…Linked List

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

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

相关文章

自定义数据 微调CLIP (结合paper)

CLIP 是 Contrastive Language-Image Pre-training 的缩写&#xff0c;是一个擅长理解文本和图像之间关系的模型&#xff0c;下面是一个简单的介绍&#xff1a; 优点&#xff1a; CLIP 在零样本学习方面特别强大&#xff0c;它可以&#xff08;用自然语言&#xff09;给出图像…

【文件系统】 F2FS文件系统学习

一、基本介绍 1、F2FS History F2FS&#xff08;Flash Friendly File System&#xff09;是专门为Nand Flash设计的一个日志型文件系统&#xff0c;于2012年12月合入Linux3.8内核&#xff0c;Google也在2018年&#xff08;Android P&#xff09;将其吸收到安卓原生版本中&…

【DL水记】循环神经网络RNN的前世今生,Transformer的崛起,Mamba模型

文章目录 RNN网络简介传统RNN网络结构RNN的分类 长-短期记忆网络 (LSTM)GRU网络横空出世的Transformer网络Self-AttentionVisionTransformer Mamba模型Reference: RNN网络简介 “当人类接触新事物时&#xff0c;他们不会从头开始思考。就像你在阅读这篇文章时&#xff0c;你会根…

最新版的GPT-4.5-Turbo有多强

OpenAI再次用实力证明了&#xff0c;GPT依然是AI世界最强的玩家&#xff01;在最新的AI基准测试中&#xff0c;OpenAI几天前刚刚发布的GPT-4-Turbo-2024-04-09版本&#xff0c;大幅超越了Claude3 Opus&#xff0c;重新夺回了全球第一的AI王座&#xff1a; 值得一提的是&#xf…

Assign Memory Resources to Containers and Pods

minikube addons enable metrics-server minikube addons enable metrics-server 是一个命令&#xff0c;用于在 Minikube 环境中启用 metrics-server 插件。 Minikube 是一个工具&#xff0c;可以在本地轻松创建和管理单节点 Kubernetes 集群&#xff0c;适合开发和测试。Mini…

二叉树进阶题目

1还原二叉树 #include<bits/stdc.h> using namespace std; const int N1e310; char pre[N],mid[N]; int w[N]; int ans; struct node{int l,r; }t[N]; int build(int prel,int prer,int midl,int midr){int ascpre[prel];int posw[asc];if(midl<pos)t[asc].lbuild(pre…

从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK

作者&#xff1a;来自 Elastic Damien Mathieu 正如我们之前所分享的&#xff0c;Elastic 致力于帮助 OpenTelemetry&#xff08;OTel&#xff09;取得成功&#xff0c;这意味着在某些情况下构建语言 SDK 的分发版本。 Elastic 在观察性和安全数据收集方面战略性地选择了 OTel…

深入挖掘C语言 ----动态内存分配

开篇备忘录: "自给自足的光, 永远都不会暗" 目录 1. malloc和free1.1 malloc1.2 free 2. calloc和realloc2.1 calloc2.2 realloc 3. 总结C/C中程序内存区域划分 正文开始 1. malloc和free 1.1 malloc C语言提供了一个动态开辟内存的函数; void* malloc (size_t s…

Python中的迭代器:深入理解与实用指南

文章目录 1. 迭代器的基本概念2. Python中的迭代器实例3. 自定义迭代器3.1 例子3.2 详细过程 4. 迭代器的高级应用5. 常见问题与解答 迭代器是Python中非常核心的概念之一&#xff0c;在面试中也会被问到。下面我会详细介绍什么是迭代器&#xff0c;使用方法&#xff0c;以及使…

爬虫 | 基于 requests 实现加密 POST 请求发送与身份验证

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目旨在实现一个简单的 Python 脚本&#xff0c;用于向指定的 URL 发送 POST 请求&#xff0c;并通过特定的加密算法生成请求头中的签名信息。这个脚本的背后是与某个特定的网络服务交互&#xff0c;发送特定格式的 JSON 数据…

vi编辑器的用法linux中的vim编辑器大全

vim的介绍 vi 和 vim 命令是linux中强⼤的⽂本编辑器, 由于Linux系统⼀切皆⽂件&#xff0c;⽽配置⼀个服务就是在修改其配置⽂件的参数。 vim 编辑器是运维⼯程师必须掌握的⼀个⼯具, 没有它很多⼯作都⽆法完成。 其中有vi和vim两种 vi和vim的区别 Vim是Vi的升级版本&#…

source map 开发优化工具

什么是 Source map 简单来说 Source map 就是一个存储信息的文件&#xff0c;里面储存着位置信息。 Source map 英文释义&#xff1a;源程序映射。 位置信息&#xff1a;转换后的代码 对应的 转换前的代码 位置映射关系。 有了 Source map&#xff0c;就算线上运行的是转换…

el-menu 该有的页面显示不出来第一个应该想到的问题首先就算检查是否多写了一个 , 导致显示不出来原有的页面

问题描述 el-menu 该有的页面显示不出来第一个应该想到的问题首先就算检查是否多写了一个 , 导致显示不出来原有的页面 如图所示多写了一个&#xff0c;就会导致该有的页面显示不出来。

nVisual在线网络规划设计软件

●01● nVisual在线网络规划设计软件 在信息化快速发展的今天&#xff0c;网络基础设施的建设与优化变得尤为关键。为了满足现代通信行业对高效、精准的网络规划需求&#xff0c;nVisual在线网络规划设计软件应运而生&#xff0c;它通过集成先进的GIS技术和网络规划工具&#…

OpenHarmony鸿蒙南向开发案例:【智能门铃】

样例简介 智能门铃通过监控来访者信息&#xff0c;告诉主人门外是否有人按铃、有陌生人靠近或者无人状态。主人可以在数字管家中远程接收消息&#xff0c;并根据需要进行远程取消报警和一键开锁。同时&#xff0c;也可以通过室内屏幕获取门外状态。室内屏幕显示界面使用DevEco…

人工智能,如何走好下一步

以下文章来源&#xff1a;金台资讯 2023年&#xff0c;生成式人工智能在全球范围爆火&#xff0c;引发了人工智能领域新一轮的科技竞赛。眼下&#xff0c;人工智能不仅能辅助科学研究与艺术创作&#xff0c;还能实现自动驾驶、打造“无人农场”和“黑灯工厂”&#xff0c;成为解…

数据很重要,ASM磁盘组损坏,使用AMDU来抢救

欢迎关注“数据库运维之道”公众号&#xff0c;一起学习数据库技术! 本期将为大家分享“数据很重要&#xff0c;ASM磁盘组损坏&#xff0c;使用AMDU来抢救”的处置案例。这个案例对个人来说比较经典&#xff0c;下面我将把自己的处理思路进行整理与总结。 环境信息&#xff1…

户用光伏业务解决方案

一、光伏户用痛点 1、推广难 没有成熟的推广与拓客能力&#xff0c;造成时间和金钱大量浪费。 2、管理难 有内部和外部几十或者上百推广人员&#xff0c;管理纷杂&#xff0c;效率低下。 3、无制度 缺少有效的人员管理制度与系统&#xff0c;分辨不出优秀人才&#xff0c…

Let‘s Forkin‘ Dance!Tanssi 激励测试网活动全面启动

作者&#xff1a;Tanssi 编译&#xff1a;OneBlock 作为 Tanssi 社区和生态系统发展的重要推手&#xff0c;Tanssi 基金会推出了 Incentivized TestNet 活动 —— Let’s Forkin’ Dance。该活动旨在激励顶尖参与者&#xff0c;推动社区增长和网络活动&#xff0c;为今年晚些时…

c语言-快速排序

文章目录 代码工程运行结果 这个是升序排列&#xff0c;如果想降序排列,将下面两行的符号反过来即可; arr[right] < arr[key] arr[left] > arr[key]代码工程 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>void swap(int *v1, int *v2) {int temp *v1;*v1 …