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

文章目录

  • 本篇代码位置
  • 顺序表和链表
    • 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.rhkb.cn/news/385241.html

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

相关文章

html+css 实现单选按钮动画(input radio按钮)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

【第二天】计算机网络 HTTP请求报文和响应报文是什么样的 HTTP请求方式有哪些 GET请求和POST请求的区别

HTTP请求报文和响应报文是什么样的&#xff1f; 我去&#xff0c;以前都没怎么研究过这个。 客户端发送一个请求给服务器&#xff0c;服务器根据请求报文中的信息进行处理&#xff0c;并将处理结果放到响应报文中返回给客户端。 URL HTTP使用URL (Uniform Resource Locator&…

OriginPro 2024b (学习版) 绘制3D坐标下 边际直方图

OriginPro 2024b (学习版) 绘制3D坐标下 边际直方图 时间 2024年7月27日 1.导入数据 需要3列数据&#xff0c;分别作为x,y,z, 其中z值随便设置。快速设置z值的方法&#xff1a;在第4行“F(x)”输入1&#xff0c;这一列的值全设置为1了。 设置x,y,z的方法如下&#xff1a;点击…

WHAT - 一个 Github 仓库的 License 如何解读

目录 一、背景二、解读许可证说明的作用常见的开源许可证类型使用他人代码仓库时需要注意的事项结论 实践作为开发者1. 选择许可证类型2. 在 README 文件中编写许可证信息 作为使用者1. 确定权限2. 了解和遵守条款 总结 一、背景 我们经常在一些 Github 仓库里看到 License 部…

如何知道一个字段在selenium中是否可编辑?

这篇文章将检查我们如何使用Java检查selenium webdriver中的字段是否可编辑。 我们如何知道我们是否可以编辑字段&#xff1f;“readonly”属性控制字段的可编辑性。如果元素上存在“readonly”属性&#xff0c;则无法编辑或操作该元素或字段。 因此&#xff0c;如果我们找到一…

【每日一篇】使用图神经网络进行交通速度预测的上下文感知知识图谱框架【为了自己方便读论文】

Context-aware knowledge graph framework for traffic speed forecasting using graph neural network 论文链接&#xff1a; https://arxiv.org/abs/2407.17703 翻译&#xff1a; 摘要 人类流动在空间和时间上受到城市环境的密切影响&#xff0c;构成了理解交通系统的重…

electron TodoList网页应用打包成linux deb、AppImage应用

这里用的是windows的wsl的ubuntu环境 electron应用打包linux应用需要linux下打包&#xff0c;这里用windows的wsl的ubuntu环境进行操作 1&#xff09;linux ubuntu安装nodejs、electron 安装nodejs&#xff1a; sudo apt update sudo apt upgrade ##快捷安装 curl -fsSL http…

7-23学习笔记

一、异常 即程序中一些程序处理不了的特殊情况 Exception 能被程序本身处理( try-catch )&#xff0c; Error 是无法处理的(只能尽量避免)。 1、异常类 Exception 见过的异常 NullPointerException ArrayIndexoutOfBoundException等 String strnull;System.out.println(st…

《python程序语言设计》第6章14题 估算派值 类似莱布尼茨函数。但是我看不明白

这个题提供的公式我没看明白&#xff0c;后来在网上找到了莱布尼茨函数 c 0 for i in range(1, 902, 100):a (-1) ** (i 1)b 2 * i - 1c a / bprint(i, round(4 / c, 3))结果 #按题里的信息&#xff0c;但是结果不对&#xff0c;莱布尼茨函数到底怎么算呀。

Docker学习与实战

一、Docker安装 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine配置docker yum源 sudo yum install -y yum-utils配置阿里云docker仓库 sudo y…

学习记录:ESP32控制舵机 FREERTOS BLE

控制舵机 PWM信号 PWM信号是一种周期性变化的方波信号&#xff0c;它有两个关键参数&#xff1a; 周期&#xff08;Period&#xff09;&#xff1a;一个完整的PWM信号的时间长度&#xff0c;通常用秒&#xff08;s&#xff09;或毫秒&#xff08;ms&#xff09;表示。占空比…

前端开发:HTML与CSS

文章目录 前言1.1、CS架构和BS架构1.2、网页构成 HTML1.web开发1.1、最简单的web应用程序1.2、HTTP协议1.2.1 、简介1.2.2、 http协议特性1.3.3、http请求协议与响应协议 2.HTML概述3.HTML标准结构4.标签的语法5.基本标签6.超链接标签6.1、超链接基本使用6.2、锚点 7.img标签8.…

算法:BFS解决 FloodFill 算法

目录 FloodFill 算法 题目一&#xff1a;图像渲染 题目二&#xff1a;岛屿数量 题目三&#xff1a;岛屿的最大面积 题目四&#xff1a;被围绕的区域 FloodFill 算法 在递归搜索回溯中已经说到过 FloodFill 算法了&#xff0c;但是那里是用 dfs 解决的&#xff0c;这里会使…

【Web开发手礼】探索Web开发的魅力(十一)-Vue(1)配置环境、创建导航栏、各页面整体框架

主要讲解了vue的下载、配置环境、项目创建、导航栏、页面整体框架&#xff01;&#xff01;&#xff01; 文章目录 前言 配置环境 终端 安装Nodejs 安装vue/cli 启动vue自带的图形化项目管理界面 基本概念 script部分 template部分 style部分 第三方组件 创建导航栏 总结 前言 …

数据结构——单链表OJ题(上)

目录 一、移除链表元素 1.思路 2.注意 3.解题 二、反转链表 思路1&#xff1a;三指针翻转法 &#xff08;1&#xff09;注意 &#xff08;2&#xff09;解题 思路2&#xff1a;头插法 &#xff08;1&#xff09;注意 &#xff08;2&#xff09;解题 三、链表的中间结…

目标检测算法:深入探索与前沿展望

大家好&#xff0c;我是一名测试开发工程师&#xff0c;已经开源一套【自动化测试框架】和【测试管理平台】&#xff0c;欢迎大家联系我&#xff0c;一起【分享测试知识&#xff0c;交流测试技术】 在人工智能的浩瀚星空中&#xff0c;目标检测算法无疑是一颗璀璨的明星&#x…

uniapp的h5,读取本地txt带标签的文件

效果图 使用的回显的标签是u-parse&#xff0c;下面的网址讲了这个标签的相关 https://www.cnblogs.com/huihuihero/p/12978903.html 导入此插件 https://ext.dcloud.net.cn/plugin?id364 使用 uni.request({// 本地文件url: "/static/互联网医院医师端用户协议.txt…

开始尝试从0写一个项目--前端(三)

器材管理板块 添加器材管理导航 src\views\home\Home.vue src\router\index.js src\views\equipment\Equipment.vue <template><div>hello!</div></template> 测试 搜索导航分页查询 src\views\equipment\Equipment.vue <template><div&…

51.TFT_LCD液晶屏驱动设计与验证(4)

&#xff08;1&#xff09;顶层文件&#xff1a; module tft_colorbar(input clk ,input reset_n ,output hsync ,output vsync ,output [23:0] rgb_tft ,output tft_bl ,output …

LeetCode算法——滑动窗口矩阵篇

1、长度最小的子数组 题目描述&#xff1a; 解法&#xff1a; 设一个 for 循环来改变指向窗口末尾的指针&#xff0c;再不断抛弃当前窗口内的首元素 最终确定满足条件的最小长度 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int …