数据结构学习之顺序表

        在C语言学习到一定阶段之后,接下来我们就进入到了数据结构的部分内容。

目录

数据结构与线性表

顺序表

        顺序表分类:

        接下来我们要写一段代码实现动态顺序表。

首先我们需要准备三个文件:

1.接下来我们要定义一个数据表

2.当创建号我们的顺序表之后,我们要对他进行初始化

3.而动态内存创建后就必须有销毁

4.接下来我们要对顺序表进行各种操作:增删插改

尾部插入数据

 头部插入数据

尾部删除数据

头部删除数据:

指定位置之前插入数据

指定位置查找数据

完整的代码:


数据结构与线性表

        数据就像草原的一群羊一样,如果你要在草原上找到一个叫做“咩咩”的羊很难,但是如果你要找一头“3号”羊是比较简单的。数据结构就是像羊圈管理羊群一样管理数据。

        因此可以说,数据结构就是计算机存储和组织数据的方式。

        数组就是一种很基础的数据结构,用来存储一群同类型的数据。但是随着我们要对数据进行的操作愈加复杂(访问、修改、插入数据等等等等),频繁的访问数组已经严重影响了计算机运行的效率,因此简单的数组已经无法满足我们的需要了,因此我们需要进入第一个数据结构类型——线性表。

        线性表是n个具有相同特性的数据元素的有限序列,是一种广泛应用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串等等。

        但是注意线性表在逻辑上是连续的线性结构,但是物理上不一定是连续的。线性表在物理上储存的时候通常以数组和链式结构的形式储存。

顺序表

        顺序表在底层上是数组。

        那么既然已经有数组了,我们为什么需要顺序表呢?举例说明:

int a[100]={1,2,3,4,...X...};

        对于如上所示的100个元素的数组a。如果我们要修改其中一个数字就找先遍历数组找到对应元素修改,如果要插入和删除数组的话,都需要遍历这个100个元素的数组。这个效率显然是很低的。因此我们需要一个更好用、效率更高的工具:顺序表。

        顺序表是在数组的基础上加上了增删查改等方法的一种储存形式。顺序表的特性是在物理结构上连续,在逻辑结构上也连续。

        这是一个固定长度的数组

int a[10]={0};

        这是动态内存开辟出来的数组,确定大小后再去申请。

int *arr

        顺序表分类:

        静态顺序表:

​
​
Stack SeqList
{int arr[100];//定长数组int size;//顺序表当前有效的数据个数}​​

        动态顺序表:

​
Stack Seqlist
{int *arr;//int size//有效数字个数int capacity;//空间大小
};​

相较于静态顺序表,动态顺序表可以动态增容。

        接下来我们要写一段代码实现动态顺序表。

首先我们需要准备三个文件:

Seqlist.c——实现顺序表的方法
Seqlist.h——顺序表结构,顺序表声明,方法

test.c——测试代码

1.接下来我们要定义一个数据表

2.当创建号我们的顺序表之后,我们要对他进行初始化

这里我们用传值返回就会报错,原因:传值返回是值拷贝,但是这里s1没有值。
所以这里要用传址返回。

3.而动态内存创建后就必须有销毁

4.接下来我们要对顺序表进行各种操作:增删插改

声明:

尾部插入数据

原理展示:

要申请多大的空间?

 增容一般是2到3倍(2倍更常见)。因为一次性给太多空间就会像静态顺序表那样浪费大量空间而得不偿失,而过少就会导致需要频繁地扩容而导致程序运行效率过低

 尾部插入数据函数一:

尾部插入数据函数二:

因此这部分的代码为:

但是这个结构是比较脆弱的,如果用户输入了这么一个东西,它就会报错:读取访问权限冲突。

	SLPushback(NULL, 5);

 所以我们要对这个函数进行改造。

温柔的方式

//温柔的解决方式
if (ps->arr == NULL)
{return;
}
if (ps->size == ps->capacity)//空间不够了
{
//code
}

暴力的方式

//暴力判断
assert(ps->arr!= NULL);
//等价于assert(ps)

尾部插入的代码:

//尾部插入数据
void SLPushback(SL* ps, STDatatype x)
{//暴力判断assert(ps->arr!= NULL);//等价于assert(ps)if (ps->size == ps->capacity)//空间不够了{//申请空间//要增容只能用realloc函数,不能用malloc和callocint newcapacity = ps->capacity == 0 ? 4:2*ps->capacity;STDatatype*tmp = realloc(ps->arr, newcapacity * 2 * sizeof(STDatatype));//tmp指的是结构体当中的数组arrif (tmp==NULL )//realloc可能申请失败所以要判断{perror("realloc error");return 1;//程序推出}//申请成功ps->arr = tmp;ps->capacity = newcapacity;}ps->arr[ps->size++] = x;
}
 头部插入数据

 原理图:

如图所示,如果要申请空间挪动数据的话从最后一位开始

 代码为:

尾部删除数据

原理图:

        

代码: 

  

头部删除数据:

原理图:

代码:  

指定位置之前插入数据

原理:

代码; 指定位置删除数据

原理图:

        代码:

指定位置查找数据

查找数据相对来说比较简单,这里受限于篇幅,只讲解暴力查找的算法,即循环遍历数组

完整的代码:

Seqlist.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
//定义顺序表的结构//#define N 100
//静态顺序表
//struct SeqList
//{
//	int arr[N];
//	int size;//有效数据个数
//};
typedef int STDatatype;
//这里是为了将来方便替换数组存储数据的类型
// 如果将来需要替换数据类型为char,只需要将int改为char即可//动态顺序表
typedef struct SeqList
{STDatatype* arr; int size;//有效数据个数int capacity;//顺序表空间大小
}SL;//这是为了将来为了方便调用结构体//顺序表初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDestory(SL* ps);
//校验顺序表空间够不够
void SLCheckCapacity(SL* ps);
//顺序表的打印
void SLPrint(SL s);
//顺序表头部/尾部插入数据
void SLPushback(SL*ps, STDatatype x);//尾部插入数据
void SLPushfront(SL*ps, STDatatype x);//头部插入数据void SLPopback(SL*ps);	//尾部删除数据
void SLPopfront(SL*ps);//头部删除数据
//指定位置之前插入数据/删除数据/查找数据
void SLInsert(SL* ps, int pos,STDatatype x);//插入数据
//ps表示在ps所在的数组里插入数据
//pos在指定顺序表里下标的位置
//x为插入的数据
void SLDelete(SL* ps,int pos);//删除数据
int SLFind(SL* ps, STDatatype x);//查找数据

Seqlist.c

#define _CRT_SECURE_NO_WARNINGS
#include"Seqlist.h"
//Seqlist.c——实现顺序表的方法
//Seqlist.h——顺序表结构,顺序表声明,方法
//顺序表的初始化
void SLInit(SL *ps)
{ps->arr = NULL;//需要包含头文件<stdlib.h>ps->size=ps->capacity=0;}
//顺序表的销毁
void SLDestory(SL*ps)
{if (ps->arr)//判断数据表的数组不为空{free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
//校验顺序表空间够不够
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity)//空间不够了{//申请空间//要增容只能用realloc函数,不能用malloc和callocint newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDatatype* tmp = realloc(ps->arr, newcapacity * 2 * sizeof(STDatatype));//tmp指的是结构体当中的数组arrif (tmp == NULL)//realloc可能申请失败所以要判断{perror("realloc error");return 1;//程序推出}ps->arr = tmp;ps->capacity = newcapacity;}
}
//顺序表的打印
void SLPrint(SL s)
{for (int i = 0;i < s.size;i++){printf("%d ", s.arr[i]);}printf("\n");
}
//尾部插入数据
void SLPushback(SL* ps, STDatatype x)
{//温柔的方式// if(ps == NULL)// {//	return;// }//暴力判断assert(ps);//等价于assert(ps->arr!= NULL);//校验空间够不够SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}
//头部插入数据
void SLPushfront(SL* ps, STDatatype x)
{assert(ps);SLCheckCapacity(ps);//先让顺序表中整体的数据向后移动一位。for (int i = ps->size - 1;i >=0;i--){ps->arr[i+1]=ps->arr[i];//最后为arr[1]=arr[0]}ps->arr[0] = x;ps->size++;
}//尾部删除数据
void SLPopback(SL* ps, STDatatype x)
{assert(ps);assert(ps->size != 0);//顺序表不为空//这段代码是否存在无所谓:ps->arr[ps->size - 1] = -1;--ps->size;
}
//头部删除数据
void SLPopfront(SL* ps)
{assert(ps);assert(ps->size != 0);//数据表整体向前移动一位for (int i = 0;i <= ps->size - 1;i++){ps->arr[i] = ps->arr[i+1];}ps->size--;
}
//指定位置之前插入数据
void SLInsert(SL* ps, int pos, STDatatype x)
{assert(ps);//pos必须>=0且<=sizeassert(pos>=0&&pos<=ps->size);SLCheckCapacity(ps);//校验空间够不够//让pos位置及之后的数据集体向后一位for (int i = ps->size-1;i >= pos;i--){ps->arr[i+1] = ps->arr[i];//最后为arr[pos+1]=arr[pos]}//pos位置空出来了ps->arr[pos] = x;ps->size++;
}
//指定位置删除数据
void SLDelete(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos <ps->size);for (int i=pos;i<ps->size-1;i++){ps->arr[i] = ps->arr[i+1];//最后为arr[size-2]=arr[size-1]}ps->size--;}
//指定位置查找数据
int SLFind(SL* ps, STDatatype x)
{assert(ps);//遍历数组查找for (int i = 0;i <= ps->size - 1;i++){if (x == ps->arr[i]){//找到了return i;}else {continue;}}return -1;//无效的下标表示没找到
}

test.c

 

#define _CRT_SECURE_NO_WARNINGS
#include"Seqlist.h"
void SLtest1()
{SL s1;SLInit(&s1);//这里我们不能用传值返回//传值返回是值拷贝,但是这里s1没有值//所以这里要用传址返回//增删查改操作。//顺序表的插入//测试尾插SLPushback(&s1,1);SLPushback(&s1,2);SLPushback(&s1,3);SLPushback(&s1,4);//测试头插SLPushfront(&s1, 5);SLPushfront(&s1, 6);SLPrint(s1);// 测试头删SLPopfront(&s1);SLPopfront(&s1);SLPrint(s1);// 测试尾删SLPopback(&s1);SLPopback(&s1);SLPrint(s1);//顺序表的销毁SLDestory(&s1);
}
void SLtest2()
{SL s1;//初始化SLInit(&s1);//尾部插入数据SLPushback(&s1, 1);SLPushback(&s1, 2);SLPushback(&s1, 3);SLPushback(&s1, 4);//在指定位置之前插入数据SLInsert(&s1, 0, 99);SLInsert(&s1, s1.size, 88);SLPrint(s1);//99 1 2 3 4 88//删除指定位置的数据SLDelete(&s1, 2);SLPrint(s1);//查找指定数据int F=SLFind(&s1, 3);if (F >= 0){printf("找到了,位置是%d\n",F);}else{printf("没找到\n");}销毁SLDestory(&s1);
}
int main()
{SLtest1();SLtest2();return 0;
}

        顺序表的内容并没有结束,但是受限于篇幅原因我只能先到这里了,感谢各位读者朋友的阅读,求一个赞,谢谢。

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

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

相关文章

C# wpf

学习网址&#xff1a;控件的父类们 - WPF中文网 - 从小白到大佬 控件的父类&#xff1a; 由此我们可以得出结论&#xff0c;控件的父类们(准确的说&#xff0c;应该叫父类的父类的父类)&#xff0c;至少有如下几个类型&#xff1a; DispatcherObjectDependencyObjectVisualU…

JavaEE-多线程实战02

接上 多线程编程实战01 第三个多线程程序 package thread.test;//定义了一个叫MyThread3的类&#xff0c;实现了Runable接口,所以它必须重写run()方法 class MyThread3 implements Runnable {Overridepublic void run() {//线程执行的具体内容//进入一个无限循环&#xff0c;…

【无报错,亲测有效】如何在Windows和Linux系统中查看MySQL版本

如何在Windows和Linux系统中查看MySQL版本 MySQL作为最流行的开源关系型数据库管理系统之一&#xff0c;了解如何查看其版本信息对于开发者和数据库管理员来说是常用的一个基本操作。本文将详细介绍在Windows和Linux系统中查看MySQL版本的方法。 文章目录 如何在Windows和Linu…

数字智慧方案5961丨智慧能源与运维云平台解决方案(52页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;智慧能源与运维云平台解决方案 在当今数字化时代&#xff0c;能源管理与设备运维的智能化、高效化成为企业发展的关键。智慧能源与运维云平台解决方案应运而生&#xff0c;为企业提供了全面且先进的能源管理和运维手段…

Qt指南针

Qt写的指南针demo. 运行结果 滑动调整指针角度 实现代码 h文件 #ifndef COMPASS_H #define COMPASS_H#include <QWidget> #include <QColor>class Compass : public QWidget {Q_OBJECT// 可自定义属性Q_PROPERTY(QColor backgroundColor READ backgroundColor WRI…

北大新媒体运营黄金提示词 | 北大Deepseek系列第七弹《DeepSeek与新媒体运营》,13所大学系列一站下载

今天大师兄给大家推荐的是北京大学Deepseek系列第七弹《DeepSeek与新媒体运营》。 本文档系统介绍了DeepSeek模型在新媒体运营中的应用&#xff0c;技术原理、实践案例及行业挑战。 适用人群&#xff1a;新媒体运营人员、AI研究者、企业决策者。 思维导图 napkin生成 《老…

2025年真实面试问题汇总(一)

Spingboot中如何实现有些类是否加载 在 Spring Boot 中可以通过 条件化配置&#xff08;Conditional Configuration&#xff09; 来控制某些类是否加载。Spring Boot 提供了一系列 Conditional 注解&#xff0c;允许根据特定条件动态决定 Bean 或配置类是否生效。以下是常见的…

综合案例建模(2)

文章目录 螺旋片端盖多孔扭转环作业一作业二作业三 螺旋片端盖 上视基准面画草图&#xff0c;拉伸250&#xff0c;向外拔模15度 以地面圆&#xff08;如果不行就转换实体引用&#xff09;&#xff0c;创建螺旋线&#xff0c;锥形螺纹线15度向外 前视基准面去画草图 以上一步草图…

Qt5与现代OpenGL学习(三)纹理

把第一张图放到D盘的1文件夹里面&#xff1a;1.png triangle.h #ifndef WIDGET_H #define WIDGET_H#include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLVertexArrayObject> #include <QOpenGLShaderProgram> #include <QOpen…

这是一款好用的PDF工具!

用户习惯有时确实非常顽固&#xff0c;想要改变它可能需要漫长的时间。 比如PDF软件&#xff0c;我认为国产的福/昕、万/兴等软件都非常不错&#xff0c;它们贴合国人的使用习惯&#xff0c;操作起来非常顺手。但因为我习惯使用DC&#xff0c;所以在处理PDF文档时&#xff0c;…

轻松实现CI/CD: 用Go编写的命令行工具简化Jenkins构建

在工作中&#xff0c;随着开发维护的服务越来越多&#xff0c;在很长的一段时间里&#xff0c;我来回在多个服务之间开发、构建、查看容器是否启动成功。尤其是开发测试阶段&#xff0c;需要打开jenkins页面、搜索应用、再构建、再打开rancher页面、搜索应用&#xff0c;这一连…

第十六届蓝桥杯 2025 C/C++B组第一轮省赛 全部题解(未完结)

目录 前言&#xff1a; 试题A&#xff1a;移动距离 试题C&#xff1a;可分解的正整数 试题D&#xff1a;产值调整 试题E&#xff1a;画展布置 前言&#xff1a; 我参加的是第一轮省赛&#xff0c;说实话第一次参加还是比较紧张的&#xff0c;真到考场上看啥都想打暴力&…

Qt Creator环境编译的Release软件放在其他电脑上使用方法

本文解决的问题&#xff1a;将Qt Creator环境编译的exe可执行程序放到其他电脑上不可用情况 1、寻找windeployqt工具所在路径" D:\Qt5.12.10\5.12.10\msvc2015_64\bin" &#xff0c;将此路径配置到环境变量&#xff1b; 2、用Qt Creator环境编译出Release版本可执行…

使用skywalking进行go的接口监控和报警

安装 helm upgrade --install skywalking ./skywalking-v1 --namespace skywalking --create-namespace 查看安装结果 kubectl get pod -n skywalking NAME READY STATUS RESTARTS AGE elasticsearch-6c4ccbf99f-ng6sk 1/1 …

2025年- H16-Lc124-169.多数元素(技巧)---java版

1.题目描述 2.思路 3.代码实现 import java.util.Arrays;public class H169 {public int majorityElement(int[] nums) {Arrays.sort(nums);int nnums.length;return nums[n/2];}public static void main(String[] args){H169 test07new H169();int[] nums{2,2,1,1,1,2,2};int…

k8s术语pod

Pod概览 理解Pod Pod是kubernetes中你可以创建和部署的最小也是最简的单位,pod代表着集群中运行的进程。 Pod中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络IP,管理容器如何运行的策略选项。Pod代表着部署的一个单位:kubemetes中应用的一个实例,可能由一个…

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》章节思维导图

今天看到了几本书的思维导图&#xff0c;感触颇深&#xff0c;如果思维导图只是章节安排&#xff0c;这样的思维导图有毛用。 给出《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》实质内容章节的思维导图。思维导图的优势是逻辑关系和知识…

Nacos简介—4.Nacos架构和原理二

大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Distro协议 6.Nacos内核设计之通信通道 7.Nacos内核设计之寻址机制 8.服务注册发现模块的注册中心的设计原理 9.服务注册发现模块的注册中心的服务数…

【MySQL】复合查询与内外连接

目录 一、复合查询 1、基本查询回顾&#xff1a; 2、多表查询&#xff1a; 3、自连接&#xff1a; 4、子查询&#xff1a; 单列子查询 多行子查询&#xff1a; 多列子查询&#xff1a; 在from语句中使用子查询&#xff1a; 5、合并查询&#xff1a; union&#xff1…

后端工程师需要掌握哪些基础技能

后端工程师是构建系统核心逻辑的关键角色&#xff0c;需要掌握从基础到进阶的完整技术栈。以下是结合国内实际开发需求的技能树整理&#xff0c;附带学习建议&#xff1a; 一、编程语言&#xff08;至少精通1-2种&#xff09; # 国内主流选择&#xff08;按优先级排序&#x…