当前位置: 首页 > news >正文

顺序表——“数据结构与算法”

各位CSDN的uu们你们好呀,今天小雅兰的内容是数据结构与算法里面的顺序表啦,在我看来,数据结构总体上是一个抽象的东西,关键还是要多写代码,下面,就让我们进入顺序表的世界吧


线性表

顺序表


线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

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


 顺序表

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

顺序表就是数组,但是在数组的基础上,它还要求数据是从头开始连续存储的,不能跳跃间隔 

顺序表一般可以分为:

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

#define _CRT_SECURE_NO_WARNINGS 1
#define N 7
#include"SeqList.h"
typedef int SLDateType;
typedef struct SeqList
{SLDateType arr[N];//定长数组size_t size;//表示数组中存储了多少数据
}SL;

 动态顺序表:使用动态开辟的数组存储。

#define _CRT_SECURE_NO_WARNINGS 1
#define N 7
#include"SeqList.h"
typedef int SLDateType;
typedef struct SeqList
{SLDateType* arr;//指向动态开辟的数组size_t size;//表示数组中存储了多少数据size_t capicity;//数组实际能存储数据的空间容量是多大
}SL;

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。  

在这里,所有函数命名风格都是跟着STL走的,方便小雅兰日后的学习!!! 


顺序表的初始化:

void SeqListInit(SL* ps)//顺序表的初始化
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

注意:在这里,不可以使用传值调用的方式,只能使用传址调用的方式

void SeqListInit(SL ps)//顺序表的初始化
{ps.arr = NULL;ps.size = ps.capacity = 0;
}

万万不能使用这样的方式初始化,因为:在函数传参的时候,形参是实参的一份临时拷贝,对形参的修改并不会影响实参

 顺序表的打印:

void SeqListPrint(SL* ps)//顺序表的打印
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}

扩容:

void SeqListCheckCapacity(SL* ps)//检查空间,如果满了,进行扩容
{//如果没有空间或者空间不足,那么我们就扩容if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDateType* tmp = (SLDateType*)realloc(ps->arr, newcapacity * sizeof(SLDateType));if (tmp == NULL){printf("realloc fail!\n");exit(-1);}ps->arr = tmp;ps->capacity = newcapacity;}
}

顺序表销毁:

void SeqListDestroy(SL* ps)//顺序表销毁
{free(ps->arr);ps->arr = NULL;ps->capacity = ps->size = 0;
}

尾插:

void SeqListPushBack(SL* ps, SLDateType x)//尾插
{SeqListCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}

尾删:

void SeqListPopBack(SL* ps)//尾删
{assert(ps->size > 0);ps->size--;
}

 头插:

void SeqListPushFront(SL* ps, SLDateType x)//头插
{SeqListCheckCapacity(ps);//挪动数据int end = ps->size - 1;while (end >= 0){ps->arr[end + 1] = ps->arr[end];end--;}ps->arr[0] = x;ps->size++;
}

头删:

void SeqListPopFront(SL* ps)//头删
{assert(ps->size > 0);//挪动数据int begin = 0;while (begin < ps->size-1){ps->arr[begin] = ps->arr[begin+1];++begin;}ps->size--;
}
另一种写法:
void SeqListPopFront(SL* ps)//头删
{assert(ps->size > 0);//挪动数据int begin = 1;while (begin < ps->size){ps->arr[begin - 1] = ps->arr[begin];++begin;}ps->size--;
}

 顺序表查找:

//顺序表查找
//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDateType x)
{int i = 0;for (i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}

 指定pos下标位置插入:

// 顺序表指定pos下标位置插入x
void SeqListInsert(SL* ps, size_t pos, SLDateType x)
{温柔的写法//if (pos > ps->size || pos < 0)//{//	printf("pos invalid!\n");//}//粗暴的写法assert(pos <= ps->size || pos >= 0);SeqListCheckCapacity(ps);//挪动数据int end = ps->size - 1;while (end >= pos){ps->arr[end + 1] = ps->arr[end];end--;}ps->arr[pos] = x;ps->size++;
}

 然后,写出了这个函数的功能之后,我们发现:可以对之前写的头插和尾插搞一些事情,下面,我们开始搞事情!!!

头插和尾插:

void SeqListPushBack(SL* ps, SLDateType x)//尾插
{SeqListInsert(ps, ps->size, x);
}
void SeqListPushFront(SL* ps, SLDateType x)//头插
{SeqListInsert(ps, 0, x);
}

 删除pos位置的数据:

//顺序表删除pos位置的数据
void SeqListErase(SL* ps, size_t pos)
{assert(pos < ps->size || pos >= 0);int begin = pos + 1;while (begin < ps->size){ps->arr[begin - 1] = ps->arr[begin];++begin;}ps->size--;
}

写出这个函数的功能之后,我们又可以搞事情啦!!!

头删和尾删:

void SeqListPopBack(SL* ps)//尾删
{SeqListErase(ps, 0);
}
void SeqListPopFront(SL* ps)//头删
{SeqListErase(ps, ps->size - 1);
}

菜单:

void menu()
{printf("#############################################\n");printf("\n");printf("###################1.头插#####################\n");printf("\n");printf("###################2.头删#####################\n");printf("\n");printf("###################3.尾插######################\n");printf("\n");printf("###################4.尾删######################\n");printf("\n");printf("###################5.打印#####################\n");printf("\n");printf("###################0.exit#####################\n");printf("\n");printf("##############################################\n");
}

其实,最好不要一上来就写菜单,先写单元测试,菜单不方便调试

 测试菜单函数:

void MenuTest()
{SL s1;SeqListInit(&s1);int input = 0;int x;while (input != -1){menu();scanf("%d", &input);switch (input){case 1:printf("请输入你要头插的数据,以-1结束:");while (x != -1){SeqListPushFront(&s1, x);scanf("%d", &x);}break;case 2:SeqListPopFront(&s1);break;case 3:printf("请输入你要尾插的数据,以-1结束:");while (x != -1){SeqListPushBack(&s1, x);scanf("%d", &x);}break;case 4:SeqListPopBack(&s1);break;case 5:SeqListPrint(&s1);break;case 0:printf("退出程序\n");break;default:printf("输入错误,请重新输入\n");}}
}

源代码如下:

SeqList.h的内容:

#pragma once
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include<assert.h>
#define N 7
typedef int SLDateType;
//顺序表的动态存储
typedef struct SeqList
{SLDateType* arr;//指向动态开辟的数组size_t size;//表示数组中存储了多少数据size_t capacity;//数组实际能存储数据的空间容量是多大
}SL;
//基本增删查改接口
void SeqListInit(SL* ps);//顺序表的初始化
void SeqListPrint(SL* ps);//顺序表的打印
void SeqListCheckCapacity(SL* ps);//检查空间,如果满了,进行扩容
void SeqListDestroy(SL* ps);//顺序表销毁
void SeqListPushBack(SL* ps, SLDateType x);//尾插
void SeqListPopBack(SL* ps);//尾删
void SeqListPushFront(SL* ps, SLDateType x);//头插
void SeqListPopFront(SL* ps);//头删
//顺序表查找
//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDateType x);
//顺序表指定pos下标位置插入x
void SeqListInsert(SL* ps, size_t pos, SLDateType x);
//顺序表删除pos位置的数据
void SeqListErase(SL* ps, size_t pos);

SeqList.c的内容:

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SeqListInit(SL* ps)//顺序表的初始化
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
void SeqListPrint(SL* ps)//顺序表的打印
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
void SeqListCheckCapacity(SL* ps)//检查空间,如果满了,进行扩容
{//如果没有空间或者空间不足,那么我们就扩容if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDateType* tmp = (SLDateType*)realloc(ps->arr, newcapacity * sizeof(SLDateType));if (tmp == NULL){printf("realloc fail!\n");exit(-1);}ps->arr = tmp;ps->capacity = newcapacity;}
}
void SeqListDestroy(SL* ps)//顺序表销毁
{free(ps->arr);ps->arr = NULL;ps->capacity = ps->size = 0;
}
void SeqListPushBack(SL* ps, SLDateType x)//尾插
{SeqListCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}
void SeqListPopBack(SL* ps)//尾删
{assert(ps->size > 0);ps->size--;
}
void SeqListPushFront(SL* ps, SLDateType x)//头插
{SeqListCheckCapacity(ps);//挪动数据int end = ps->size - 1;while (end >= 0){ps->arr[end + 1] = ps->arr[end];end--;}ps->arr[0] = x;ps->size++;
}
void SeqListPopFront(SL* ps)//头删
{assert(ps->size > 0);//挪动数据int begin = 1;while (begin < ps->size){ps->arr[begin - 1] = ps->arr[begin];++begin;}ps->size--;
}
//顺序表查找
//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDateType x)
{int i = 0;for (i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}
// 顺序表指定pos下标位置插入x
void SeqListInsert(SL* ps, size_t pos, SLDateType x)
{温柔的写法//if (pos > ps->size || pos < 0)//{//	printf("pos invalid!\n");//}//粗暴的写法assert(pos <= ps->size || pos >= 0);SeqListCheckCapacity(ps);//挪动数据int end = ps->size - 1;while (end >= pos){ps->arr[end + 1] = ps->arr[end];end--;}ps->arr[pos] = x;ps->size++;
}
//顺序表删除pos位置的数据
void SeqListErase(SL* ps, size_t pos)
{assert(pos < ps->size || pos >= 0);int begin = pos + 1;while (begin < ps->size){ps->arr[begin - 1] = ps->arr[begin];++begin;}ps->size--;
}

好啦,小雅兰今天的内容就到这里啦,数据结构的的确确是一个麻烦的东西,还要加油呀!!!

 

相关文章:

顺序表——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是数据结构与算法里面的顺序表啦&#xff0c;在我看来&#xff0c;数据结构总体上是一个抽象的东西&#xff0c;关键还是要多写代码&#xff0c;下面&#xff0c;就让我们进入顺序表的世界吧 线性表 顺序表 线性表 线性表&…...

嵌入式Linux从入门到精通之第十六节:U-boot分析

简介 u-boot最初是由PPCBoot发展而来的,可以引导多种操作系统、支持多种架构的CPU,它对PowerPC系列处理器的支持最为完善,而操作系统则对Linux系统的支持最好目前已成为Armboot和PPCboot的替代品。 特点: 主要支持操作系统:Linux、NetBSD、 VxWorks、QNX、RTEMS、ARTOS、L…...

UART 串口通信

第18.1讲 UART串口通信原理讲解_哔哩哔哩_bilibili 并行通信 一个周期同时发送8bit的数据&#xff0c;占用引脚资源多 串行通信 串行通信的通信方式&#xff1a; 同步通信 同一时钟下进行数据传输 异步通信 发送设备和接收设备的时钟不同 但是需要约束波特率&#xff08;…...

【硬件】P沟道和N沟道MOS管开关电路设计

场效应管做的开关电路一般分为两种&#xff0c;一种是N沟道&#xff0c;另一种是P沟道&#xff0c;如果电路设计中要应用到高端驱动的话&#xff0c;可以采用PMOS来导通。P沟道MOS管开关电路PMOS的特性&#xff0c;Vgs小于一定的值就会导通&#xff0c;当Vgs<0,即Vs>Vg,管…...

中移杭研一面经历

文章目录 1、常用的Java元注解@Documented@Target@Retention@Override@Deprecated@Inherited@Repeatable@Native2、Java注解的原理3、spring boot starter开发过程1、原理浅谈2、大概步骤3、项目介绍1、常用的Java元注解 @Documented @Documented 是一个标记注解,没有成员变…...

如何成为一名全栈工程师:专业建议与技能要求

作为一名全栈工程师&#xff0c;你需要拥有跨越前端、后端、数据库等多个领域的技能&#xff0c;并能够将它们整合起来构建出完整的应用程序。因此&#xff0c;成为一名全栈工程师需要你掌握多种技术&#xff0c;具备较强的编程能力和系统设计能力。下面&#xff0c;我将从以下…...

MySQL架构篇

一、进阶学习环境说明 1.1 MySQL服务器环境 Linux虚拟机&#xff1a;CentOS 7 MySQL&#xff1a;MySQL5.7.30 在Linux服务器中安装MySQL&#xff1a; ps.如果有自己的云服务器&#xff0c;可忽略前两步&#xff0c;直接进行第三步 1.2 服务器日志文件说明 MySQL是通过文件系统对…...

Redhat7.6安装weblogic10.3.6(超详细,有图文)

一、环境 linux版本&#xff1a;Redhat 7.6 weblogic版本:WLS10.3.6 jdk版本&#xff1a;jdk1.8.0 下载网址&#xff1a;https://www.oracle.com/technetwork/middleware/weblogic/downloads/index.html 1.安装vsftpd服务&#xff0c;将部署环境使用JDK文件和wls服务文件…...

dashboard疏散主机提示报错:无法疏散主机...处理方法、openstack虚拟机状态卡在重启处理方法、openstack在数据库修改虚拟机状态的方法

文章目录dashboard疏散主机提示报错&#xff1a;无法疏散主机...处理方法报错说明【状态卡在reboot状态】解决方法【登录nova数据库修改虚拟机信息】首先获取nova数据库的密码登录nova数据库并做修改验证信息是否修改成功再次迁移并验证报错说明【虚拟机状态error也会导致疏散失…...

力扣:轮转数组(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3…...

Vue计算属性Computed

30. Vue计算属性Computed 1. 定义 Computed属性是Vue中的一个计算属性&#xff0c;是一种基于其它属性值计算而来的属性值&#xff0c;具有缓存机制&#xff0c;在依赖的属性值发生变化时会重新计算。 使用computed属性可以避免在模板中书写过多的计算逻辑&#xff0c;提高代…...

实验四:搜索

实验四&#xff1a;搜索 1.填格子 题目描述 有一个由数字 0、1 组成的方阵中&#xff0c;存在一任意形状的封闭区域&#xff0c;封闭区域由数字1 包围构成&#xff0c;每个节点只能走上下左右 4 个方向。现要求把封闭区域内的所有空间都填写成2 输入要求 每组测试数据第一…...

本地开发vue项目联调遇到访问接口跨域问题

本地开发vue项目联调遇到访问接口跨域问题 修改本地的localhost 一&#xff1a;按winr打开运行窗口&#xff0c;输入drivers &#xff0c;然后回车 二&#xff1a;打开etc文件夹&#xff0c;然后用记事本的方式打开里面的hosts文件&#xff0c; 三&#xff1a;这时我们就可…...

Vue键盘事件的使用

前言 在vue中&#xff0c;我们经常会用到键盘事件&#xff0c;不管是我们按下某个键&#xff0c;其实都是一次键盘事件的调用&#xff0c;下面就介绍下Vue中的键盘事件 先写一段代码&#xff0c;这里我选择的键盘事件是keyup,当然用keydown也是没问题的 问题来了&#xff0c;…...

抓包工具fiddler详细使用教程

各位做测试的同学想必对抓包工具fiddler并不陌生&#xff0c;但是很多同学可能没有总结过它的用法&#xff0c;下面我总结了fiddler一些常用的用法。 Web端抓包配置 打开Fiddler&#xff0c;Tools -> Fiddler Options -> HTTPS 配置完后记得要重启Fiddler 选中Decrpt …...

raspberry Pi 连接蓝牙(小爱同学)

参数valueraspberry pi MOdel4B&#xff0c;4Gbbluetooth MOdel小爱同学writeTime2023年 2月11日 下午13&#xff1a;14分raspberry System ModelLinux raspberrypi 5.15.61-v8 #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux 连接蓝牙 请在小爱同学app上…...

解决launch:program .exe does not exist

二. 程序的运行和调试 1.launch.json 复制下列代码至launch.json&#xff0c;并根据指导做出相对/绝对路径修改 用 IntelliSense 了解相关属性。 {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.micros…...

ETL --事实表

每一个事实表通过表的粒度来定义。事实表的粒度是事件度量的定义。我们必须至始至终按照度量如何在 现实世界中理解来规定事实表的粒度。 所有的事实表包含了一组关联到维表的外键&#xff0c;而这些维表提供了事实表度量的上下文。大多数的事实表还 包括了一个或者多个数值型…...

手工数据采集耗时耗力?Smartbi数据填报实现数据收集分析自动化

企业在日常经营管理过程中&#xff0c;往往需要收集很多内外部的信息&#xff0c;清洗整理后再进行存储、分析、呈现、决策支持等各种作业&#xff0c;如何高效收集结构化数据是企业管理者经常要面对的问题。传统手工的数据采集方式不仅耗费了大量人力时间成本&#xff0c;还容…...

应用实战|微信小程序开发示例--多人聊天互动空间

“超能力”数据库&#xff5e;拿来即用&#xff0c;应用开发人员再也不用为撰写API而发愁。MemFire Cloud 为开发者提供了简单易用的云数据库&#xff08;表编辑器、自动生成API、SQL编辑器、备份恢复、托管运维&#xff09;&#xff0c;很大地降低开发者的使用门槛。 本示例是…...

iMeta | 浙江农科院卢立志/曾涛联合中南大学湘雅医院揭示人参皂苷Rg3缓解肝脏铁死亡的新机制

点击蓝字 关注我们一种生物活性人参皂苷改善非酒精性脂肪性肝炎中氧化磷脂积累引起的肝细胞铁死亡iMeta主页&#xff1a;http://www.imeta.science研究论文● 原文: iMeta(IF 33.2, 中科院双一区Top)● 英文题目: A bioactive ginsenoside alleviates hepatocellular ferroptos…...

CVE-2016-2183漏洞自查与修复指南:你的Nginx/Apache还在用有问题的SSL/TLS协议吗?

CVE-2016-2183漏洞深度解析与实战修复&#xff1a;从检测到防护的全链路方案 凌晨三点&#xff0c;运维团队的告警系统突然响起——安全扫描报告显示生产环境存在SSL/TLS协议信息泄露风险。这不是普通的漏洞警报&#xff0c;而是可能直接导致加密通信被破解的CVE-2016-2183。作…...

树莓派3B+安装OpenMediaVault(OMV)后WiFi配置失效的快速修复指南

1. 问题现象与原因分析 最近在树莓派3B上折腾OpenMediaVault&#xff08;OMV&#xff09;时遇到了一个典型问题&#xff1a;安装完OMV后&#xff0c;原本配置好的WiFi突然无法连接了。这个现象特别常见于使用Raspberry Pi OS Lite系统的用户&#xff0c;我自己用的就是Bookworm…...

MTools开箱即用:5分钟在K8s部署Web版AI工具,图片音视频全能处理

MTools开箱即用&#xff1a;5分钟在K8s部署Web版AI工具&#xff0c;图片音视频全能处理 1. 为什么选择MTools Web版 MTools Web版是一款集成了图片处理、音视频编辑、AI智能工具和开发辅助功能的现代化工具套件。与传统的桌面软件不同&#xff0c;它可以直接在浏览器中运行&a…...

亚马逊Buy for Me代购服务全流程实测:从下单到收货的完整避坑手册

亚马逊Buy for Me代购服务实战解析&#xff1a;从入门到精通的完整指南 跨境购物早已不是新鲜事&#xff0c;但每次看到海外电商平台上那些国内买不到的好物&#xff0c;心里总免不了痒痒的。亚马逊最新推出的Buy for Me服务&#xff0c;或许正是解决这一痛点的钥匙。作为一名长…...

为Qwen-VL“点亮”视觉思维:从注意力热力图洞察多模态对齐的深层逻辑

1. 理解Qwen-VL的视觉思维机制 当你第一次看到Qwen-VL这类视觉语言模型时&#xff0c;可能会好奇它究竟是如何"看"图片的。想象一下&#xff0c;你正在教一个小朋友看图说话&#xff1a;小朋友会先扫视整张图片&#xff0c;然后目光停留在某些关键区域&#xff0c;最…...

Omni-Vision Sanctuary 集成 MySQL 数据库:自动化图像元数据管理与检索方案

Omni-Vision Sanctuary 集成 MySQL 数据库&#xff1a;自动化图像元数据管理与检索方案 1. 场景痛点与解决方案 数字内容创作领域正面临一个普遍挑战&#xff1a;随着AI生成图像的爆发式增长&#xff0c;如何高效管理海量图片资产成为棘手问题。某电商设计团队负责人曾向我们…...

Stats与其他Go统计库对比分析:为什么选择这个无依赖解决方案

Stats与其他Go统计库对比分析&#xff1a;为什么选择这个无依赖解决方案 【免费下载链接】stats A well tested and comprehensive Golang statistics library package with no dependencies. 项目地址: https://gitcode.com/gh_mirrors/sta/stats 在Go语言生态系统中&a…...

Java网络协议解析核心源码剖析(Netty+Spring Boot双栈实测):从Raw Socket到自动反序列化全链路解密

第一章&#xff1a;Java网络协议解析核心源码剖析&#xff08;NettySpring Boot双栈实测&#xff09;&#xff1a;从Raw Socket到自动反序列化全链路解密Java 网络通信的底层能力并非止步于 Spring Boot 的 RestController 抽象层——其真实脉搏深埋于 Netty 的 ChannelPipelin…...

为什么钉钉、飞书、企微都在做 CLI?这个开源项目给出了最极致的答案

❝AI Agent 很聪明&#xff0c;但面对真实的专业软件&#xff0c;它就是个"睁眼瞎"。CLI-Anything 说&#xff1a;我来治。❞先说一个扎心的事实2026年了&#xff0c;AI Agent 能写代码、能做分析、能聊天能画画——但你让它打开 Blender 建个模&#xff1f;让它用 G…...