【初阶数据结构篇】顺序表的实现(赋源码)

文章目录

  • 本篇代码位置
  • 顺序表和链表
    • 1.线性表
    • 2.顺序表
    • 2.1 概念与结构
    • 2.2分类
      • 2.2.1 静态顺序表
      • 2.2.2 动态顺序表
    • 2.3 动态顺序表的实现
      • 2.3.1动态顺序表的初始化和销毁及打印
      • 2.3.2动态顺序表的插入
        • 动态顺序表的尾插
        • 动态顺序表的头插
        • 动态顺序表的在指定位置插入数据
      • 2.3.3动态顺序表的删除
        • 动态顺序表的尾删
        • 动态顺序表的头删
        • 动态顺序表的在指定位置删除数据
      • 2.3.4动态顺序表查找指定数据

本篇代码位置

代码位置

顺序表和链表

1.线性表

​ 线性表(linearlist)是n个具有相同特性的数据元素的有限序列。线性表是⼀种在实际中⼴泛使⽤的 数据结构,常见的线性表:顺序表、链表、栈、队列、字符串······

​ 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,线性 表在物理上存储时,通常以数组和链式结构的形式存储。


2.顺序表

2.1 概念与结构

​ 概念:顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采⽤数组存储。

顺序表和数组的区别?

顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝。可以这么理解,我们使用数组来存储数据,并提供了增删查改数据的接口(函数),这样组织和存储数据的结构我们将它称为顺序表。

2.2分类

2.2.1 静态顺序表

概念:使用定长数组存储元素

在这里插入图片描述

  • 缺陷:显而易见的,空间一定,给少了不够用,给多了太浪费

2.2.2 动态顺序表

概念:不存储数组,而是存储一个指向一块动态开辟的内存空间的指针

在这里插入图片描述

  • 优点:按需开辟,可增容

    故我们一般都使用动态顺序表


2.3 动态顺序表的实现

2.3.1动态顺序表的初始化和销毁及打印

创建顺序表,并将其中的指针置为NULL,容量和有效数据个数置为0,销毁大致相同,不过如果arr指针非空,不要忘了释放动态申请的空间

SeqList.h(其中方法会一一讲到)

  • 定义顺序表结构
  • 将存储数据类型重命名(方便之后替换->例如我们要求顺序表内存储char类型数据,只用改一行代码即可)
  • 所写的函数的声明,声明的时候参数只需要类型就可以了,名字加不加都一样
#pragma once
#include <stdio.h>
#include<stdlib.h>
#include <assert.h>typedef int sldatatype;
typedef struct Seqlist
{sldatatype* arr;sldatatype size;sldatatype capacity;
} sl;
void slinit(sl*);//初始化
void sldestroy(sl*);//销毁void slprint(sl*);//打印
void checkcapacity(sl*);//判断空间是否足够
void slpushback(sl*, sldatatype);//尾插
void slpushfront(sl*, sldatatype);//头插void slpopfront(sl*);//头删
void slpopback(sl*);//尾删//在指定位置插入和删除数据
void slinsert(sl*, sldatatype, int);
void slfrase(sl*, int);//查找指定数据int slfind(sl*, sldatatype);

test.c

  • 用来测试我们写的函数(函数的调用)
  • 这一部分就是自己写的时候用的测试用例,随便什么都行

最好是写一个方法测试一次,不然找错误的时候会很痛苦😜

	sl s;//要改变s结构体之中的内容,别忘了传地址#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void sltest1()
{sl s;slinit(&s);slpushback(&s, 1);slpushback(&s, 2);slpushback(&s, 6);slpushback(&s, 5);int m=slfind(&s, 7);printf("%d\n", m);//slpushfront(&s, 2);//slpushfront(&s, 3);//slinsert(&s, 1, 0);//slinsert(&s, 2, 6);//slinsert(&s, 1,0 );//slfrase(&s, 1);//slfrase(&s, 0);//slfrase(&s, 1);//slpopback(&s);//slpopback(&s);//slpopback(&s);//slpopback(&s);//slpopback(&s);slpushback(NULL, 6);//slpopfront(&s);//slpopfront(&s);//slpopfront(&s);//slpopfront(&s);//slpopfront(&s);//slpopfront(&s);slprint(&s);sldestroy(&s);
}
int main()
{sltest1();return 0;
}

SeqList.c

函数方法的实现,重点重点!!!

在每一个方法的第一排都使用assert宏来判断ps是否为空(避免使用时传入空指针,后续解引用都会报错)

void slinit(sl* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->size = 0;
}void sldestroy(sl*ps)
{assert(ps);if (ps->arr){free(ps->arr);ps->arr = NULL;}ps->capacity = ps->size = 0;
}

考虑到每次测试方法时调试会很麻烦,于是先写一个打印顺序表的方法

void slprint(sl* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}
}
  • 遍历就行了,和打印数组一样的

2.3.2动态顺序表的插入

插入数据的时候一定要判断空间是否足够,不足要增容,一般2倍或3倍增容!!!

SeqList.c

养成好习惯,不要用arr直接接收动态开辟空间的地址,否则开辟失败arr变为NULL,连原来的内存块都找不到了,这就造成了内存泄漏!!!

void slcheckcapacity(sl* ps)
{assert(ps);if (ps->capacity == ps->size){//增容//若capacity为0,给个默认值,否则乘以2int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;sldatatype* tmp = (sldatatype*)realloc(ps->arr, newcapacity * sizeof(sldatatype));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}}
动态顺序表的尾插

SeqList.c

void slpushback(sl* ps, sldatatype x)
{assert(ps);slcheckcapacity(ps);ps->arr[ps->size++] = x;
}
  • 插入后size++即可了
动态顺序表的头插

SeqList.c

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++;
}
  • 先让每个数据往后一位,注意一定要从后往前挪,否则数据会被覆盖

  • 记得size++

动态顺序表的在指定位置插入数据

SeqList.c

void slinsert(sl* ps, sldatatype x, int pos)
{assert(ps);assert(pos >= 0 && pos <= ps->size);slcheckcapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
  • 类似头插,涉及到pos以及之后数据的向后移动,还是从后往前挪动
  • size++

2.3.3动态顺序表的删除

动态顺序表的尾删

删除数据的时候一定要判断顺序表是否为空,即size不能为0!!!

SeqList.c

void slpopback(sl* ps)
{assert(ps && ps->size);ps->size--;//ps->arr[ps->size] = 0;多余了,没有必要
}
  • 只要让size–即可,不影响后来的插入(数据会被覆盖)
动态顺序表的头删

SeqList.c

void slpopfront(sl* ps)
{assert(ps && ps->size);for (int i = 0; i <ps->size-1 ; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
  • 让每一位向前移动一位,从前往后挪,防止数据覆盖
  • 记得size–
动态顺序表的在指定位置删除数据

SeqList.c

void slfrase(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];}ps->size--;
}
  • 类似头删,让pos以及之后的数据向前一位,从前往后挪
  • size–

2.3.4动态顺序表查找指定数据

SeqList.c

int slfind(sl* ps, sldatatype x)
{assert(ps);int i = 0;int flag = 0;for (i = 0; i < ps->size; i++){if(ps->arr[i]==x){flag = 1;break;}}if (flag)return 1;else{return -1;}
}
  • 遍历就完事了,相信各位已经熟练掌握了(❁´◡`❁)
  • 如果找到返回1,没找到就返回-1(使用bool类型也是可以滴)

SeqList.c(完整版)

#include "Seqlist.h"
void slinit(sl* ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}void sldestroy(sl*ps)
{assert(ps);if (ps->arr){free(ps->arr);ps->arr = NULL;}ps->capacity = ps->size = 0;
}void slprint(sl* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}
}void slcheckcapacity(sl* ps)
{assert(ps);if (ps->capacity == ps->size){//增容//若capacity为0,给个默认值,否者乘以2int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;sldatatype* tmp = (sldatatype*)realloc(ps->arr, newcapacity * sizeof(sldatatype));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}}void slpushback(sl* ps, sldatatype x)
{assert(ps);slcheckcapacity(ps);ps->arr[ps->size++] = x;
}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 slpopback(sl* ps)
{assert(ps && ps->size);ps->size--;//ps->arr[ps->size] = 0;多余了,没有必要
}void slpopfront(sl* ps)
{assert(ps && ps->size);for (int i = 0; i <ps->size-1 ; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}void slinsert(sl* ps, sldatatype x, int pos)
{assert(ps);assert(pos >= 0 && pos <= ps->size);slcheckcapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}void slfrase(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];}}int slfind(sl* ps, sldatatype x)
{assert(ps);int i = 0;int flag = 0;for (i = 0; i < ps->size; i++){if(ps->arr[i]==x){flag = 1;break;}}if (flag)return 1;else{return -1;}
}

以上就是顺序表的实现方法啦,各位大佬有什么问题欢饮在评论区指正,您的支持是我创作的最大动力!❤️
请添加图片描述

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

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

相关文章

区块链——hardhat使用

一、引入hardhat yarn add --dev hardhat // 引入验证合约的插件 yarn add --dev nomicfoundation/hardhat-verify 二、创建hardhat项目 yarn hardhat 三、编写我们的合约 四、编译我们的合约 yarn hardhat compile 五、编写脚本部署合约以及验证合约 // 获取hardhat环境对象 c…

Python操作Redis指南

文本主要介绍使用Python中的redis-py库来操作Redis数据库&#xff0c;包括安装必要的包、建立和关闭连接、执行增删改查操作以及处理可能的异常。这些操作将在Python应用程序中与Redis数据库进行有效的交互。 一. 简介和包的安装 Redis是一种开源的内存数据结构存储&#xff…

Jmeter混合压测(2407)

一 压测需求&#xff1a; 电商作为服务端&#xff0c;至少需要满足并发量,QPS:100/s,TPS:20/s。例如场景&#xff1a; 电商交易中&#xff0c;商品图片请求量最多&#xff0c;电商服务端需要满足并发请求查询图片信息。各家可能会并发请求同一家电商商品、订单等内容。 二 压…

代码随想录算法训练营day7 | 454.四数相加II、383.赎金信、15.三数之和、18.四数之和

文章目录 454.四数相加II思路 383.赎金信思路 15.三数之和思路剪枝去重 18.四数之和思路剪枝去重复习&#xff1a;C中的类型转换方法 总结 今天是哈希表专题的第二天 废话不多说&#xff0c;直接上题目 454.四数相加II 建议&#xff1a;本题是 使用map 巧妙解决的问题&#x…

HarmonyOS(45) 控件拖动或者拖拽PanGesture

PanGesture实现控件拖动的效果&#xff0c;通过拖动的坐标位置调用position或者translate方法来更新UI的位置。效果见下图&#xff1a; 具体代码如下&#xff1a; // xxx.ets Entry Component struct PanGestureExample {State offsetX: number 0State offsetY: number 0pos…

【AI学习指南】轻量级模型-用 Ollama 轻松玩转本地大模型

目录 探索 最小的AI模型 发现 其他轻量级模型 用 Ollama 轻松玩转本地大模型 本地大模型 Ollama 快速上手 安装 手动安装 下载ollama二进制文件 添加 Ollama 作为启动服务(推荐) 安装 CUDA 驱动程序(可选 - 适用于 Nvidia GPU) 安装 ROCm(可选 - 对于 Radeo…

Typesript的type和interface的异同?

详解TypeScript中type与interface的区别_javascript技巧_脚本之家 一、相同的地方 1、都可以用来定义对象&#xff0c;描述函数 我们在用typescript开发的时候经常要用到数据类型定义&#xff0c;比如我们写一个接口或者函数的时候定义传参数据类型及字段等。这样子方便知道这…

代码随想录day21 二叉树最后一天 || 669修剪二叉树 108将有序数组转变为平衡搜索二叉树 538把搜索二叉树变为累加二叉树

669修剪二叉树 力扣题目链接 题目描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果…

K8s 核心组件——API Server

1. Kubernetes API Server 概述 1.1 基本概念 Kubernetes API Server&#xff08;API Server&#xff09;是 Kubernetes 的核心组件之一&#xff0c;负责暴露 Kubernetes API 给用户和客户端&#xff0c;接收和处理来自客户端的请求&#xff0c;并将其存储到 etcd 中。Kubern…

花几千上万学习Java,真没必要!(三十一)

集合&#xff1a; 1、数组的特性&#xff1a; 2、ArrayList&#xff08;动态数组&#xff09;&#xff1a; 测试代码1&#xff1a; package listtest.com; import java.util.ArrayList; import java.util.List; public class HashCodesArrayList { public static void ma…

深入分析 Android ContentProvider (六)

文章目录 深入分析 Android ContentProvider (六)ContentProvider 的性能优化和实践案例&#xff08;续&#xff09;1. 性能优化技巧&#xff08;续&#xff09;1.6. 使用批量插入优化性能示例&#xff1a;批量插入实现 1.7. 使用 Projections 优化查询示例&#xff1a;使用 Pr…

本周热点丨快手《可灵》国际版正式上线、《王者荣耀》国际服海外下载量破5000万

7月第4周 秦彻带动《恋与深空》2.0霸榜全球 《蔚蓝档案》上线3.5周年庆典版本&#xff0c;登顶日服iOS畅销榜 《Honor of Kings》下载量突破五千万 英伟达将开发"Blackwell"的中国定制版芯片 人工智能初创公司Cohere获得5亿美元融资 Fal AI推出全新开源图像生成模型A…

reshape函数及MATLAB应用

reshape 函数在 MATLAB 中是一个非常有用的函数&#xff0c;通过重新排列现有元素来重构数组。它允许你重新调整数组&#xff08;或矩阵&#xff09;的尺寸&#xff0c;而不改变其数据。这个函数特别适用于当你需要将一个矩阵或数组从一种结构转换为另一种结构时&#xff0c;只…

AFSim 仿真系统--任务处理器入门指南

任务处理器 任务处理器&#xff08;WSF_TASK_PROCESSOR&#xff09;是一个WSF处理器&#xff0c;它提供了检查轨迹管理器中的数据&#xff08;轨迹&#xff09;并对其采取行动的能力。这些行动包括&#xff1a; *向下属分配任务 *激活或停用传感器或干扰器 *开火武器 *操纵平台…

昇思MindSpore 应用学习-DCGAN生成漫画头像-CSDN

日期 心得 昇思MindSpore 应用学习-DCGAN生成漫画头像&#xff08;AI代码学习&#xff09; DCGAN生成漫画头像 在下面的教程中&#xff0c;我们将通过示例代码说明DCGAN网络如何设置网络、优化器、如何计算损失函数以及如何初始化模型权重。在本教程中&#xff0c;使用的动…

vue2和el-input无法修改和写入,并且不报错

文章目录 一. 业务场景描述二. 原因分析三.解决方案3.1 方案一 原生标签&#xff08;不建议&#xff09;3.2 方案二 父子传递&#xff08;不建议&#xff09;3.3 方案三 vuex&#xff0c;pinia 状态传值&#xff08;不建议&#xff09;3.4 方案四 vue初始化属性 &#xff08;建…

Java从入门到精通(十三)~ 枚举和注解

晚上好&#xff0c;愿这深深的夜色给你带来安宁&#xff0c;让温馨的夜晚抚平你一天的疲惫&#xff0c;美好的梦想在这个寂静的夜晚悄悄成长。 文章目录 目录 前言 一、枚举 1.1 枚举的概念 ​编辑 1.2 枚举的特点 1.3 枚举的实际运用 1. 状态机&#xff0c;描述属性的…

Nginx配置详解

1. Nginx安装 进入到/usr/local目录下&#xff0c;执行命令&#xff1a; yum install -y nginx通过如下命令启动nginx服务 systemctl start nginx通过如下命令&#xff0c;设置nginx开启自启动 systemctl enable nginxnginx默认占用80端口。 访问ip:80&#xff0c;可以看到…

Open3D 点云按xyz轴等距切片

目录 一、概述 1.1原理 1.2实现步骤 1.3应用 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2按x轴切片 3.3按y轴切片 3.4按z轴切片 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff…

Java中线程池的基本使用

参考这个课程&#xff0c;讲的非常详细 27.线程池使用步骤总结_哔哩哔哩_bilibili 应用场景 商品秒杀 文件上传 订票系统 自定义线程池&#xff08;让我们了解底层逻辑的&#xff09; 构造方法 饱和机制 就是我们的队列饱和后我们该怎么处理 是拒绝这个任务还是啥…