数据结构:顺序表的奥秘

🎉个人名片:

🐼作者简介:一名乐于分享在学习道路上收获的大二在校生
🐻‍❄个人主页🎉: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.hqwc.cn/news/518255.html

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

相关文章

Golang搭建grpc环境

简介 OS : Windows 11 Golang 版本: go1.22.0 grpc : 1.2 protobuffer: 1.28代理 没有代理国内环境下载不了库七牛CDN &#xff08;试过可用&#xff09; go env -w GOPROXYhttps://goproxy.cn,direct阿里云代理(运行grpc时下载包出现报错 ): go env -w GOPROXYhttps://mirr…

el-table 表格多选, 批量删除功能

一、基础的多选el-table ElementUI 提供了多选行table&#xff0c;同时若依框架也提供了成熟的多选表格。 1.table基础结构 需要绑定selection-change方法 <el-tablev-loading"loading"stripe:data"productList"selection-change"handleSelect…

Vue+Vue CLI学习

1、Vue基础 1.1、Vue简介 &#xff08;1&#xff09;Javascript框架 &#xff08;2&#xff09;简化Dom操作 &#xff08;3&#xff09;响应式数据驱动 vue基础&#xff1b;vue-cli;vue-router;vuex;element-ui;vue3 vue文件包括html、css、js 1.2、第一个Vue程序 Vue …

如何进行渗透测试以提高软件安全性

对于各种规模的企业和组织来说&#xff0c;软件安全是一个至关重要的问题。随着网络攻击越来越复杂&#xff0c;软件中的漏洞越来越多&#xff0c;确保你的软件安全比以往任何时候都更重要。提高软件安全性的一个有效方法是渗透测试&#xff08;penetration testing&#xff09…

【python基础学习10课_面向对象、封装、继承、多态】

一、类与对象 1、类的定义 在类的里面&#xff0c;称之为方法。 在类的外面&#xff0c;称之为函数。类&#xff1a;人类&#xff0c;一个族群&#xff0c;是一个群体类的语法规则&#xff1a;class 自定义的类名():属性 -- 变量方法 -- 函数类&#xff0c;首字母大写&#x…

如何在有/没有备份的情况下恢复华为上已删除的视频?6 个推荐选项

“我不小心删除了华为手机上的一堆视频。我怎样才能把它们找回来&#xff1f;我在谷歌上也找不到它们”。——来自知乎 在我们日常生活的喧嚣中&#xff0c;意外时有发生。无论是由于华为手机上的无意删除、恢复出厂设置、病毒感染、数据损坏还是系统故障&#xff0c;这些视频…

基于单片机的机动车智能远光灯系统设计

目 录 摘 要 I Abstract II 引 言 1 1 主要研究内容及总体设计方案 3 1.1 主要研究内容 3 1.2 系统总体方案选择 3 1.3 系统功能的确定 4 2 硬件电路的设计 5 2.1 单片机控制模块设计 5 2.2 液晶显示模块电路设计 7 2.3 远近灯光电路设计 9 2.4 按键电路设计 9 2.5 超声波电路…

【QA-SYSTEMS】CANTATA-解决Jenkins中build Cantata报错

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 解决Jenkins中build Cantata测试项目报找不到license server的错误。 2、 问题场景 在Jenkins中build Cantata测试项目&#xff0c;报错“Failed to figure out the license server correctly”。 3、软硬件环…

vue+Nodejs+Koa搭建前后端系统(九)-- 上传图片

web2.0的到来使网页世界正式进入了寒武纪&#xff0c;各式各样的多媒体资源屡见不鲜&#xff0c;上传资源变得刻不容缓&#xff01; 前言 本文是在该系列的基础上&#xff0c;针对前后端代码的修改。 准备 HTTP上传图片时Content-Type值常见的有2种&#xff1a;application…

java集合(泛型数据结构)

1.泛型 1.1泛型概述 泛型的介绍 泛型是JDK5中引入的特性&#xff0c;它提供了编译时类型安全检测机制 泛型的好处 把运行时期的问题提前到了编译期间 避免了强制类型转换 泛型的定义格式 <类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: …

Vue+SpringBoot打造桃花峪滑雪场租赁系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

Python接口自动化之cookie、session应用!

以下介绍cookie、session原理及在接口自动化中的应用。 HTTP 协议是一种无状态协议&#xff0c;即每次服务端接收到客户端的请求时&#xff0c;都是一个全新的请求&#xff0c;服务器并不知道客户端的历史请求记录&#xff1b;Session 和 Cookie 的主要目的就是为了弥补 HTTP 的…