数据结构:顺序表的奥秘

🎉个人名片:

🐼作者简介:一名乐于分享在学习道路上收获的大二在校生
🐻‍❄个人主页🎉:GOTXX
🐼个人WeChat:ILXOXVJE

🐼本文由GOTXX原创,首发CSDN🎉🎉🎉
🕊系列专栏:零基础学习C语言----- 数据结构的学习之路
🐓每日一句:如果没有特别幸运,那就请特别努力!🎉🎉🎉
————————————————

🎉文章简介:

🎉本篇文章对   用C语言实现顺序表 学习的相关知识进行分享!🎉

如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作动力的源泉,让我们一起加油,一起奔跑,让我们顶峰相见!!!🎉🎉🎉

目录

一.顺序表的概念及存储结构

1.1储存结构

二.顺序表的实现

一.功能函数的实现

1.初始化函数

2.顺序表的销毁

3.顺序表的打印

4.扩容函数

5.尾插函数

6.尾删函数

7.头插函数

8.头删函数

9.插入函数

10.删除函数

11.查找函数

12.修改函数

三.总代码

四.顺序表的性能分析


一.顺序表的概念及存储结构

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

顺序表可以分为静态顺序表和动态顺序表。

1.1储存结构

静态顺序表:使用定长数组存储元素;

动态顺序表:数组的大小是根据存储的数据个数,如果满了就动态开辟出来的,相对而言不会造成空间的浪费;

二.顺序表的实现

静态顺序表 只适用于确定知道需要存多少数据的场景;

静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。例如:如果数组的大小定为200,却只储存了几十个数据,和动态的顺序表相比,空间浪费更大;所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

一.功能函数的实现(含图解)

1.初始化函数

功能:对结构体内成员进行初始化操作;

代码实现:

void InitList(SL* s)
{assert(s);        //断言,防止传入空指针s->a = (SLDateType* )malloc(sizeof(SLDateType) * 4);  if (s->a == NULL)   //这里最开始开辟四个存储数据类型的大小{perror("malloc fail");exit(-1);}s->size = 0;            //存储的有效数据个数为0s->capacity = 4;       //空间置成4
}

2.顺序表的销毁

功能:对动态开辟的空间进行销毁,空间释放

代码实现:

void DestoryList(SL* s)
{assert(s);free(s->a);       //释放动态开辟的空间s->a = NULL;      //置空s->capacity = s->size = 0;
}

3.顺序表的打印

代码实现:

void SListPrintf(SL* s)
{assert(s);if (s->size < 0)     //如果没有数据,则直接返回{return;}for (int i = 0; i < s->size; i++){printf("%d ", s->a[i]);       //遍历依次打印}printf("\n");        //打印完换行
}

4.扩容函数

功能:检查是否需要扩容

代码实现:

void CheckCapacity(SL* s)
{assert(s);if (s->capacity == s->size)    //相等则说明空间已经满了{SLDateType* tmp = realloc(s->a, sizeof(SLDateType)* 2 * s->capacity);  //二倍扩容if (tmp == NULL)    {perror("realloc fail");exit(-1);}s->a = tmp;s->capacity *= 2;}
}

5.尾插函数

功能:在顺序表最后插入一个数据

代码实现:

void PushBack(SL* s, SLDateType n)
{assert(s);CheckCapacity(s);  //检查空间是否满s->a[s->size] = n;    //直接插入到数组最后s->size++;       //有效数据个数++
}

6.尾删函数

功能: 删除顺序表的最后一个数据

代码实现

void PopBack(SL* s)
{assert(s);assert(s->size > 0);     //当数组中有效数据个数为0时,不能再删除s->size--;         //数据个数--}

7.头插函数

功能:在顺序表最前面插入一个数据

代码实现:

void PushFront(SL* s, SLDateType n)
{assert(s);CheckCapacity(s);    //检查扩容int end = s->size;    while (end>0) {s->a[end] = s->a[end - 1];   //挪动数据end--;}s->a[0] = n;         s->size++;
}

图解:

性能分析:头插一个数据,首先需要将全部数据一次往后挪一个位置,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

8.头删函数

功能:删除表中第一个元素

代码实现:

void Popfront(SL* s)
{assert(s);assert(s->size > 0);   //size为0时,不能再删除for (int i = 0; i < s->size; i++){s->a[i] = s->a[i+1];      //向前挪动数据}s->size--;
}

图解:

性能分析:头删一个数据,首先需要将全部数据一次往前挪一个位置,将第一个元素覆盖掉,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

9.插入函数

功能:在某个位置插入一个数据

代码实现:


void SListInsert(SL* s, int pos, SLDateType n)
{assert(s);assert(pos >= 0 && pos <= s->size);    //判断pos合法int end = s->size;int begin = pos;while (begin < end){s->a[end] = s->a[end - 1];   //挪动数据end--;}s->a[pos] = n;       //修改数据s->size++;
}

图解:

性能分析:中间插入一个数据和头插差不多,首先需要将该位置后面的全部数据依次往后挪一个位置,将该位置空出来,再将该数据插入,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

10.删除函数

功能:删除数组中任何位置的数据

代码实现:

void SListErase(SL* s, int pos)
{assert(s);assert(pos >= 0 && pos < s->size);    //pos范围合法判断int cur = pos;while (cur < s->size){s->a[cur] = s->a[cur+1];    //挪动位置cur++;}s->size--;}

图解:

性能分析:删除一个数据与头删差不多,首先需要待删数据位置后面全部数据依次往前挪一个位置,将待删元素覆盖掉,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

11.查找函数

功能:查找顺序表中某个数据,返回下标

代码实现:

int SListFind(SL* s,SLDateType n)
{assert(s);for (int i = 0; i < s->size; i++)    //遍历寻找{if (s->a[i] == n)     //找到了返回下标{ return i;}}printf("顺序表中无该数据\n");   exit(-1);}

性能分析:将数组中的数据遍历一遍;时间复杂度:O(N)

空间复杂度:O(1)

12.修改函数

功能:修改数组中某个数据

代码实现:

void SListModify(SL* s, int pos,SLDateType n)
{assert(s);assert(pos >= 0 && pos < s->size);s->a[pos] = n;     //直接通过下标访问修改
}

三.总代码

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLDateType;struct SeqList
{SLDateType* a;      //指向一个数组的指针int size;           //记录数据个数int capacity;       //记录容量,如果与数据个数相等就扩容
};typedef struct SeqList SL;void InitList(SL* s);void SListPrintf(SL* s);void PushBack(SL* s, SLDateType n);
void PushFront(SL* s, SLDateType n);
void PopBack(SL* s);
void Popfront(SL* s);int SListFind(SL* s,SLDateType n);void SListModify(SL* s, int pos, SLDateType n);
void SListErase(SL* s, int pos);
void SListInsert(SL* s, int pos, SLDateType n);void DestoryList(SL* s);

#include"SeqList.h"void InitList(SL* s)
{assert(s);        //断言,防止传入空指针s->a = (SLDateType* )malloc(sizeof(SLDateType) * 4);  if (s->a == NULL)   //这里最开始开辟四个存储数据类型的大小{perror("malloc fail");exit(-1);}s->size = 0;            //存储的有效数据个数为0s->capacity = 4;       //空间置成4
}void SListPrintf(SL* s)
{assert(s);if (s->size < 0)     //如果没有数据,则直接返回{return;}for (int i = 0; i < s->size; i++){printf("%d ", s->a[i]);       //遍历依次打印}printf("\n");        //打印完换行
}void CheckCapacity(SL* s)
{assert(s);if (s->capacity == s->size)    //相等则说明空间已经满了{SLDateType* tmp = realloc(s->a, sizeof(SLDateType)* 2 * s->capacity);  //二倍扩容if (tmp == NULL)    {perror("realloc fail");exit(-1);}s->a = tmp;s->capacity *= 2;}
}void PushBack(SL* s, SLDateType n)
{assert(s);CheckCapacity(s);  //检查空间是否满s->a[s->size] = n;    //直接插入到数组最后s->size++;       //有效数据个数++
}void PushFront(SL* s, SLDateType n)
{assert(s);CheckCapacity(s);    //检查扩容int end = s->size;    while (end>0) {s->a[end] = s->a[end - 1];   //挪动数据end--;}s->a[0] = n;         s->size++;
}void PopBack(SL* s)
{assert(s);assert(s->size > 0);     //当数组中有效数据个数为0时,不能再删除s->size--;         //数据个数--}void Popfront(SL* s)
{assert(s);assert(s->size > 0);   //size为0时,不能再删除for (int i = 0; i < s->size; i++){s->a[i] = s->a[i+1];      //向前挪动数据}s->size--;
}int SListFind(SL* s,SLDateType n)
{assert(s);for (int i = 0; i < s->size; i++)    //遍历寻找{if (s->a[i] == n)     //找到了返回下标{ return i;}}printf("顺序表中无该数据\n");   exit(-1);
}void SListModify(SL* s, int pos,SLDateType n)
{assert(s);assert(pos >= 0 && pos < s->size);s->a[pos] = n;     //直接通过下标访问修改
}void SListErase(SL* s, int pos)
{assert(s);assert(pos >= 0 && pos < s->size);    //pos范围合法判断int cur = pos;while (cur < s->size){s->a[cur] = s->a[cur+1];    //挪动位置cur++;}s->size--;}void SListInsert(SL* s, int pos, SLDateType n)
{assert(s);assert(pos >= 0 && pos <= s->size);    //判断pos合法int end = s->size;int begin = pos;while (begin < end){s->a[end] = s->a[end - 1];   //挪动数据end--;}s->a[pos] = n;       //修改数据s->size++;
}void DestoryList(SL* s)
{assert(s);free(s->a);       //释放动态开辟的空间s->a = NULL;      //置空s->capacity = s->size = 0;
}

四.顺序表的性能分析

问题:


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

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

下一章链表结构就可以解决这个问题;




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

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

相关文章

C#,排列组合的堆生成法(Heap’s Algorithm for generating permutations)算法与源代码

1 排列组合的堆生成法 堆生成算法用于生成n个对象的所有组合。其思想是通过选择一对要交换的元素&#xff0c;在不干扰其他n-2元素的情况下&#xff0c;从先前的组合生成每个组合。 下面是生成n个给定数的所有组合的示例。 示例&#xff1a; 输入&#xff1a;1 2 3 输出&a…

ZigBee技术与实践教程(无线传感网技术第三天)

1.MAC层规范 在IEEE802系列标准中&#xff0c;OSI参考模型的数据链路层进一步划分为逻辑链路控制子层和介子访问子层两个子层。MAC子层使用物理层提供的服务实现设备之间的数据帧传输&#xff0c;而LLC在MAC 层的基础上&#xff0c;在设备之间提供面向连接和非连接的服务&…

智慧城市的新引擎:物联网技术引领城市创新与发展

目录 一、引言 二、物联网技术与智慧城市的融合 三、物联网技术在智慧城市中的应用 1、智慧交通管理 2、智慧能源管理 3、智慧环保管理 4、智慧公共服务 四、物联网技术引领城市创新与发展的价值 五、挑战与前景 六、结论 一、引言 随着科技的日新月异&#xff0c;物…

注意!!墙裂推荐几个好用的实用小工具!一定会用到的!

前言 在开发的世界里&#xff0c;面对各种挑战和问题时&#xff0c;拥有一套合适的工具箱至关重要。这不仅能提升我们的工作效率&#xff0c;还能让复杂的任务变得简单&#xff0c;甚至在解决棘手问题的同时&#xff0c;还能让我们的心情略微舒畅。众所周知&#xff0c;有用的…

STM32F103 CubeMX ADC 驱动 PS2游戏摇杆控制杆传感器模块

STM32F103 CubeMX ADC 驱动 PS2游戏摇杆控制杆传感器模块 1. 工程配置1.1 配置debug口1.2 配置时钟1.3 配置ADC1.4 配置串口1.5 配置时钟1.6 生成工程 2. 代码编写2.1 串口代码2.2 ADC读取数据的代码 1. 工程配置 1.1 配置debug口 1.2 配置时钟 1.3 配置ADC 1.4 配置串口 1.5 …

笔记本电脑使用时需要一直插电吗?笔记本正确的充电方式

随着科技的不断发展&#xff0c;笔记本电脑已经成为人们日常生活和工作中不可或缺的电子设备。而在使用笔记本电脑时&#xff0c;很多人会有一个疑问&#xff0c;那就是笔记本电脑使用时需要一直插电吗&#xff1f;本文将就此问题展开讨论。 不一定需要一直插电&#xff0c;如果…

开源组件安全风险及应对

在软件开发的过程中&#xff0c;为了提升开发效率、软件质量和稳定性&#xff0c;并降低开发成本&#xff0c;使用开源组件是开发人员的不二选择&#xff08;实际上&#xff0c;所有软件开发技术的演进都是为了能够更短时间、更低成本地构建软件&#xff09;。这里的开源组件指…

【Web开发】深度学习HTML(超详细,一篇就够了)

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【Web开发】深度学习html(超详细,一篇就够了) &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 HTML1. HTML基础1.1 什么是HTML1.2 认识HTML标签1.3 HTML文件基本…

【linux进程信号】信号的产生

【Linux进程信号】信号的产生 目录 【Linux进程信号】信号的产生信号概念生活中的信号技术应用角度的信号注意信号概念用kill -l命令可以察看系统定义的信号列表信号处理常见方式概览 产生信号通过终端按键产生信号调用系统函数向进程发信号由软件条件产生信号由硬件异常产生信…

Linux 理解进程

目录 一、基本概念 二、描述进程-PCB 1、task_struct-PCB的一种 2、task_ struct内容分类 三、组织进程 四、查看进程 1、ps指令 2、top命令 3、/proc文件系统 4、在/proc文件中查看指定进程 5、进程的工作目录 五、通过系统调用获取进程标示符 1、getpid()/get…

css--浮动

一. 浮动的简介 在最初&#xff0c;浮动是用来实现文字环绕图片效果的&#xff0c;现在浮动是主流的页面布局方式之一。 二. 元素浮动后的特点 &#x1f922;脱离文档流。&#x1f60a;不管浮动前是什么元素&#xff0c;浮动后&#xff1a;默认宽与高都是被内容撑开&#xff0…

Redis基础篇:初识Redis(认识NoSQL,单机安装Redis,配置Redis自启动,Redis客户端的基本使用)

目录 1.认识NoSQL2.认识Redis3.安装Redis1.单机安装Redis2.配置redis后台启动3.设置redis开机自启 4.Redis客户端1.Redis命令行客户端2.图形化桌面客户端 1.认识NoSQL NoSQL&#xff08;Not Only SQL&#xff09;数据库是一种非关系型数据库&#xff0c;它不使用传统的关系型数…

ORACLE Linux(OEL) - Primavera P6EPPM 安装及分享

引言 继上一期发布的CentOS版环境发布之后&#xff0c;近日我制作了基于ORACLE Linux的P6虚拟机环境&#xff0c;同样里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机&#xff0c;请先与Oracle Primavera销售代表取得联系…

【Spring】Spring状态机

1.什么是状态机 (1). 什么是状态 先来解释什么是“状态”&#xff08; State &#xff09;。现实事物是有不同状态的&#xff0c;例如一个自动门&#xff0c;就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机&#xff0c;也就是被描述的事物的状态的数量是有…

Python 一步一步教你用pyglet制作汉诺塔游戏

目录 汉诺塔游戏 1. 抓取颜色 2. 绘制圆盘 3. 九层汉塔 4. 绘制塔架 5. 叠加圆盘 6. 游戏框架 汉诺塔游戏 汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;是一个源于印度古老传说的益智玩具。这个传说讲述了大梵天创造世界的时候&#xff0c;他做了三根金刚…

【Leetcode每日一刷】滑动窗口:209.长度最小的子数组

一、209.长度最小的子数组 1.1&#xff1a;题目 题目链接 1.2&#xff1a;解题思路 题型&#xff1a;滑动窗口&#xff1b;时间复杂度&#xff1a;O(n) &#x1faa7; 滑动窗口本质也是双指针的一种技巧&#xff0c;特别适用于字串问题 ❗❗核心思想/ 关键&#xff1a;左右…

【笔记】原油阳谋论

文章目录 石油的属性能源属性各国石油替代 金融属性黄金石油美元 油价历史油价传导路径 石油供需格局与发展供需格局各国状况美国俄罗斯沙特 产油国困境运输 分析格局分析供需平衡分析价差分析价差概念基本面的跨区模型跨区模型下的价差逻辑 长中短三期分析长期视角——供应看投…

【笔记】全国大学生GIS应用技能大赛练习总结

该总结笔记为小组成员在练习完毕了历届题目后自我总结的结果&#xff0c;如有不足之处可以在评论区提出&#xff0c;排版较乱往谅解 绘制带空洞的面要素&#xff1a; 法一&#xff1a; 1、矢量化整个区域。2、矢量化空洞区域。3、将矢量化空洞区域进行合并&#xff08;编辑器…

Spring MVC 全局异常处理器

如果不加以异常处理&#xff0c;错误信息肯定会抛在浏览器页面上&#xff0c;这样很不友好&#xff0c;所以必须进行异常处理。 1.异常处理思路 系统的dao、service、controller出现都通过throws Exception向上抛出&#xff0c;最后由springmvc前端控制器交由异常处理器进行异…

Linux C/C++下使用Lex/Yacc构建实现DBMS(Minisql)

DBMS&#xff08;数据库管理系统&#xff09;是一种用于管理和组织数据库的软件系统。它的重要性在于提供了一种有效地存储、管理和访问大量数据的方式。本文将深入探讨如何使用C语言、Lex&#xff08;词法分析器生成器&#xff09;和Yacc&#xff08;语法分析器生成器&#xf…