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

初级数据结构(一)——顺序表

文中代码源文件已上传:数据结构源码

<-上一篇 NULL        |        初级数据结构(二)——链表 下一篇->

1、顺序表的特点

1.1、数组

        现实中数据记录一般都记录在表格中,如进货单、菜单等,它们的最大特点就是有序。表述中可以用第一项、第二项、第 n 项来描述表格中某个数据或者某串数据。在 C 语言中,数组的特点恰好匹配此功能。

        由于数组在内存中的储存方式就如同列表依序排布,对数组可以用 arr[n] 或者 *(arr+n) 来迅速获得第 n-1 项数据。再加上而且数组是 C 语言的原生类型,创建数组极其便利,作为有序数据的载体着实是不二之选。

1.2、结构

        顺序表为了方便使用,除了用数组作为数据载体外,一般还包含记录数组空间大小和开辟空间大小的两个变量。常以结构体将这三个变量作为成员变量进行囊括。主要有两种创建方式:

        柔性数组顺序表( Sequence table with flexible array ):

#include <stdlib.h>//重定义数据类型
typedef int DATA;//创建并重定义结构体类型
typedef struct SeqTab
{int size;           //数据长度int capacity;       //数据空间大小DATA arr[];         //数据载体柔性数组
}SeqTab;int main()
{//开辟结构体空间SeqTab* sqList = (SeqTab*)malloc(sizeof(SeqTab) + sizeof(DATA)*4);//初始化数据长度及空间大小sqList->size = 0;sqList->capacity = 4;return 0;
}

        数组指针顺序表( Sequence table with array pointer ):

#include <stdlib.h>//重定义数据类型
typedef int DATA;//创建并重定义结构体类型
typedef struct SeqTab
{int size;           //数据长度int capacity;       //数据空间大小DATA* arr;          //数据载体数组指针
}SeqTab;int main()
{//创建结构体变量SeqTab sqList;//开辟数据载体数组空间sqList.arr = (DATA*)malloc(sizeof(DATA)*4);//初始化数据长度及空间大小sqList.size = 0;sqList.capacity = 4;return 0;
}

2、顺序表创建

        接下来以数组指针顺序表为例进行演示。

2.1、文件结构

        seqTab.h :用于创建结构体类型及声明函数;

        sqFunction.c :用于创建顺序表初始化及增删改查的函数;

        main.c :仅创建 main 函数,用作测试。

2.2、前期工作

        在 seqTab.h 中先写入以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>//用于初始化顺序表时开辟空间
#define INIT_SIZE 4//顺序表数据类型,方便顺序表储存数据类型修改
typedef int DATATYPE;//创建顺序表结构体类型
typedef struct SeqTab
{DATATYPE* data;int size;int capacity;
}SeqTab;//---------------------函数声明---------------------
//初始化顺序表
extern void DataInit(SeqTab*);//销毁顺序表
extern void DataDestory(SeqTab*);//打印顺序表
extern void DataPrint(const SeqTab*);

         在 sqFunction.c 中包含 seqTab.h 并分别创建一个初始化顺序表和销毁顺序表的函数:

#include "seqTab.h"//初始化顺序表
void DataInit(SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//为顺序表开辟空间sq->data = (DATATYPE*)malloc(INIT_SIZE * sizeof(DATATYPE));//加入判断防止空间开辟失败if (sq->data == NULL){perror("Malloc Fail");return;}//初始化记录数据长度及开辟空间长度的变量sq->size = 0;sq->capacity = INIT_SIZE;
}//销毁顺序表
void DataDestory(SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//释放顺序表数据空间free(sq->data);//数组指针置空sq->data = NULL;//数组长度及空间尺寸全部置0sq->size = 0;sq->capacity = 0;
}//打印顺序表
void DataPrint(const SeqTab* sq)
{//断言确保结构体指针不为空assert(sq);//遍历顺序表并逐个数据打印for (int i = 0; i < sq->size; i++){printf("%d ", sq->data[i]);}printf("\n");
}

        最后在 main.c 中包含 seqTab.h,并创建一个顺序表及初始化:

#include "seqTab.h"int main()
{//创建顺序表SeqTab sqList;//初始化顺序表DataInit(&sqList);return 0;
}

        至此,前期工作准备完毕,之后便是对顺序表的数据进行增删改查。

3、顺序表操作

3.1、增

        插入数据一般为头部插入数据、尾部插入数据及指定位置插入数据。插入数据时除了写入数据到数组中,还需时刻判断开辟的空间尺寸是否足以容纳已有数据。

        先将以下三个函数声明添加到 seqTab.h 中:

//指定位置插入数据
extern void DataInsert(SeqTab*, int, DATATYPE);
//头部插入数据
extern void DataPushHead(SeqTab*, DATATYPE);
//尾部插入数据
extern void DataPushTail(SeqTab*, DATATYPE);

        然后便是 DataInsert 函数。如图:

        据此可以轻松写出其代码。以下写入 sqFunction.c 中: 

void DataInsert(SeqTab* sq, int pos, DATATYPE data)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size){printf("Illegal Position : %d\n", pos);return;}//空间不足则创建空间if (sq->size + 1 >= sq->capacity){//申请新空间DATATYPE* ptr_newSqData = (DATATYPE*)realloc(sq->data, sizeof(DATATYPE) * (sq->capacity * 2));//空间申请结果判断if (ptr_newSqData == NULL){perror("Realloc Fail");return;}//赋予新空间地址sq->data = ptr_newSqData;//空间大小记录翻倍sq->capacity *= 2;}//数据后移直至腾出 pos 位置的空间for (int i = sq->size; i > pos; i--){sq->data[i] = sq->data[i - 1];}//写入数据*(sq->data + pos) = data;//数据长度+1sq->size++;
}

        至于头插尾插数据,只不过是上述函数 pos 位置的区别。因此:

//pos = 0 便是头插
void DataPushHead(SeqTab* sq, DATATYPE data)
{DataInsert(sq, 0, data);
}
//pos = 数据尺寸便是尾插
void DataPushTail(SeqTab* sq, DATATYPE data)
{DataInsert(sq, sq->size, data);
}

        在 main 函数里写入下列代码验证一下:

	DataInsert(&sqList, 10, 32);   //报错DataPushTail(&sqList, 10);DataPrint(&sqList);            //打印 10DataPushHead(&sqList, 20);DataPrint(&sqList);            //打印 20 10DataPushHead(&sqList, 3);DataPushTail(&sqList, 6);DataPushHead(&sqList, 8);DataPushHead(&sqList, 7);DataPushHead(&sqList, 2);DataPushTail(&sqList, 100);DataPushTail(&sqList, 432);DataPrint(&sqList);            //打印 2 7 8 3 20 10 6 10 432

        结果与预期无误。至此插入功能便已完成。

3.2、删

        正如插入数据分为头插、尾插及指定插,删除也分头删及任意位删。与插入相反,删除数据需要在数据删除结束后关注数据长度与开辟的数据空间,当空间分配过大时,对多余空间进行回收。

        同样先将以下三个函数声明添加到 seqTab.h 中:

//指定位置删除数据
extern void DataRemove(SeqTab*, int);
//删除头部数据
extern void DataPopHead(SeqTab*);
//删除尾部数据
extern void DataPopTail(SeqTab*);

         DataRemove 函数流程图如下:

        根据图中逻辑在 sqFunction.c 中写入以下:

void DataRemove(SeqTab* sq, int pos)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size - 1){printf("Illegal Position : %d\n", pos);return;}//列表不为空则执行if (sq->size - 1 >= 0){//由 pos 位开始,之后所有数据前移 1 位for (int i = pos; i < sq->size - 1; i++){sq->data[i] = sq->data[i + 1];}//数据长度-1sq->size--;}//开辟空间过大则执行if (sq->size < sq->capacity / 2){//申请新空间DATATYPE* ptr_newSqData = (DATATYPE*)realloc(sq->data, sizeof(DATATYPE) * (sq->capacity / 2));//空间申请结果判断if (ptr_newSqData == NULL){perror("Realloc Fail");return;}//赋予新空间地址sq->data = ptr_newSqData;//空间大小记录减半sq->capacity /= 2;}
}

         至于头删尾删数据,也同样是上述函数 pos 位置的区别:

//头删 pos = 0
void DataPopHead(SeqTab* sq)
{DataRemove(sq, 0);
}
//尾删 pos = 数据长度-1
void DataPopTail(SeqTab* sq)
{DataRemove(sq, sq->size - 1);
}

        之后同样是验证,将以下代码写到之前测试代码之后:

	DataRemove(&sqList, 100);    //报错DataRemove(&sqList, 3);DataPrint(&sqList);          //打印 2 7 8 20 10 6 100 432DataPopHead(&sqList);DataPrint(&sqList);          //打印 7 8 20 10 6 100 432DataPopTail(&sqList);DataPrint(&sqList);          //打印 7 8 20 10 6 100DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPopTail(&sqList);DataPrint(&sqList);          //打印 7DataPopTail(&sqList);DataPopTail(&sqList);DataPrint(&sqList);          //因为 size = 0 ,pos = -1 , 报错

         删除数据功能完毕。

3.3、改

        改数据的功能实现起来,逻辑上毫无难度可言。以下函数声明添加到 seqTab.h 中:

//修改指定位置数据
extern void DataModify(SeqTab*, int, DATATYPE);

         在 sqFunction.c 中写入:

void DataModify(SeqTab* sq, int pos, DATATYPE data)
{//数据有效性判断assert(sq);if (pos < 0 || pos > sq->size - 1){printf("Illegal Position : %d\n", pos);return;}//修改数据sq->data[pos] = data;
}

        在 main 函数中追加以下代码验证:

	for (int i = 0; i < 10; i++){DataPushTail(&sqList, i);}DataPrint(&sqList);            //打印 0 1 2 3 4 5 6 7 8 9DataModify(&sqList, 100, 30);  //报错DataModify(&sqList, 3, 30);DataPrint(&sqList);            //打印 0 1 2 30 4 5 6 7 8 9

         完毕。

3.4、查

        查到数据返回该数据的位置,查不到返回 -1 。同样很简单。 seqTab.h 中写入声明:

//在表中查找数据
extern int DataSearch(SeqTab*, DATATYPE);

        然后是 sqFunction.c 中写入:

int DataSearch(SeqTab* sq, DATATYPE data)
{//数据有效性判断assert(sq);//遍历数组for (int i = 0; i < sq->size; i++){//如果找到数据则返回下标if (sq->data[i] == data){return i;}}//遍历完毕仍找不到数据返回 -1return -1;
}

        main 函数中验证:

	int num = 1200;int pos = DataSearch(&sqList, num);if (pos == -1){printf("The number \"%d\" is not exist!\n", num);}else{printf("The position of number \"%d\" is %d\n", num, pos);}//打印不存在num = 9;pos = DataSearch(&sqList, num);if (pos == -1){printf("The number \"%d\" is not exist!\n", num);}else{printf("The position of number \"%d\" is %d\n", num, pos);}//打印 9DataModify(&sqList, DataSearch(&sqList, 8), 11001);DataPrint(&sqList);    //打印 0 1 2 30 4 5 6 7 11001 9

        至此增删改查功能实现均已完毕。除此之外,还有排序、截断等其他一系列可以自定的操作。总之,操作顺序表就是操作数组,实现起来难度几乎为 0 。

相关文章:

初级数据结构(一)——顺序表

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 NULL | 初级数据结构&#xff08;二&#xff09;——链表 下一篇-> 1、顺序表的特点 1.1、数组 现实中数据记录一般都记录在表格中&#xff0c;如进货单、菜单等&#xff0c;它们的最大特点就是…...

实现:切换页面切换标题,扩展 vue-router 的类型

布局容器-页面标题 网址&#xff1a;https://router.vuejs.org/zh/guide/advanced/meta 给每一个路由添加 元信息 数据 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…...

已通过考试和认证注册以及后续计划表

已通过考试和认证注册以及后续计划表 软考 - 计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试信息系统集成及服务项目管理人员工程类考试计划你关注的证书样子 软考 - 计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试 高级 信息系统项目管理师&…...

开源计算机视觉库OpenCV详解

目录 1、概述 2、OpenCV详细介绍 2.1、OpenCV的起源 2.2、OpenCV开发语言 2.3、OpenCV的应用领域 3、OpenCV模块划分 4、OpenCV源码文件结构 4.1、根目录介绍 4.2、常用模块介绍 4.3、CUDA加速模块 5、OpenCV配置以及Visual Studio使用OpenCV 6、关于Lena图片 7、…...

使用pytorch查看中间层特征矩阵以及卷积核参数

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 1和4是之前讲过的alexnet和resnet模型 2是分析中间层特征矩阵的脚本 3是查看卷积核参数的脚本 1设置预处理方法 和图像训练的时候用的预处理方法保持一致 2实例化模型 3载入之前的模型参数 4载入…...

HarmonyOS4.0从零开始的开发教程09页签切换

HarmonyOS&#xff08;七&#xff09;页签切换 List组件和Grid组件的使用 Tabs组件的使用 概述 在我们常用的应用中&#xff0c;经常会有视图内容切换的场景&#xff0c;来展示更加丰富的内容。比如下面这个页面&#xff0c;点击底部的页签的选项&#xff0c;可以实现“首页…...

大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例)

大电流H桥电机驱动电路的设计与解析&#xff08;包括自举电路的讲解&#xff0c;以IR2104LR7843为例&#xff09; 电机驱动板主要采用两种驱动芯片&#xff0c;一种是全桥驱动&#xff08;如&#xff1a;HIP4082&#xff09;&#xff0c;一种是半桥驱动&#xff08;如&#xff…...

windows11 windows 11 (win11 win 11) 怎么安装 Python3 ? numpy? sounddevice? 声音信号处理库?

首先确认要安装的 sounddevice 库&#xff0c;链接&#xff1a;https://python-sounddevice.readthedocs.io/en/0.4.6/ 根据文档&#xff0c;可知最新的 sounddevice 版本是 0.4.6 进入安装页面查看&#xff0c;发现 Newest sounddevice 可以使用 pip 安装&#xff0c;如下图…...

git如何配置多个远程仓库,并且进行切换

一、配置多个远程仓库并进行切换&#xff0c;请按照以下步骤进行操作&#xff1a; 打开命令行终端&#xff0c;并进入您的 Git 仓库所在的目录。添加第一个远程仓库&#xff0c;使用以下命令&#xff1a;git remote add origin <第一个远程仓库的 URL>这里将远程仓库命名…...

计算机存储单位 + 程序编译过程

C语言的编译过程 计算机存储单位 头文件包含的两种方式 使用 C/C 程序常用的IDE 常用的C语言编译器&#xff1a; 在选择编译器时&#xff0c;需考虑平台兼容性、性能优化、调试工具和开发人员的个人偏好等因素。 详细教程可转 爱编程的大丙...

vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)

目录 一、什么是Vue路由导航守卫&#xff1f; 二、全局守卫 1、beforeEach 下面是一个beforeEach的示例代码&#xff1a; 2、beforeResolve 下面是一个beforeResolve的示例代码&#xff1a; 3、afterEach 下面是一个afterEach的示例代码&#xff1a; 三、路由独享守卫…...

单片机双机通信控制跑马灯

实验要求 两个单片机各驱动8个LED灯&#xff0c;构成两个跑马灯&#xff0c;要求甲单片机LED的点亮方式是从上至下&#xff0c;首先是最上面第一个点亮、其次是前两个点亮、其次是前三个点亮……直至8个灯全部点亮&#xff0c;8个灯全部灭&#xff0c;重复这个过程&#xff0c…...

微信小程序:button微信开放能力打开客服会话分享到聊天框

文档 https://developers.weixin.qq.com/miniprogram/dev/component/button.html 打开客服会话 按钮关键属性 open-type"contact"功能按钮 <button class"mo-open-type"open-type"contact"> </button>分享 <button class&q…...

【数据结构】——队列实现二叉树的功能

前言&#xff1a;二叉树的实现方式多种多样&#xff0c;有数组实现满二叉树&#xff0c;有链表实现完全二叉树&#xff0c;今天我们就用队列来实现二叉树。 创建二叉树&#xff1a; typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTre…...

【已解决】Win7虚拟机安装VMtools报错

在做以前的实验的时候发现要用到Win7虚拟机&#xff0c;于是就安装了一个Win7的虚拟机&#xff0c;但是发现屏幕太小&#xff0c;而且来回复制文本、复制文件太不方便了&#xff0c;索性就安装了VMtools&#xff0c;发现还安装不成– 情况1 报错&#xff1a;本程序需要您将此…...

华为OD机试真题-小明找位置-2023年OD统一考试(C卷)

题目描述&#xff1a; 小朋友出操&#xff0c;按学号从小到大排成一列&#xff1b;小明来迟了&#xff0c;请你给小明出个主意&#xff0c;让他尽快找到他应该排的位置。 算法复杂度要求不高于nLog(n)&#xff1b;学号为整数类型&#xff0c;队列规模<10000&#xff1b; 输…...

2023.2版idea安装教程,现在jdk8已经过去式了,不同idea支持的jdk不同。升级jdk后idea也要随之升级

下载idea2023.2版本&#xff0c;下载之前需要删除之前的版本&#xff0c;一定要删除干净&#xff0c;删除程序要勾选那两个delete 下载路径&#xff1a;其他版本 - IntelliJ IDEA (jetbrains.com.cn) 选择2023.2版本 下载后进入安装程序&#xff0c;选择安装目录&#xff0c;然…...

CSS3技巧36:让内容垂直居中的三种方式

让内容垂直居中&#xff0c;是一个很重要的应用情景&#xff0c;在很多场合都会需要。这也是面试的时候&#xff0c;一些考官喜欢拿来初面的小题目。 这里&#xff0c;小结下让内容垂直居中的三种方式。 当然&#xff0c;读者如果有更好的方法&#xff0c;也可以提出来。 基本…...

空间运算设备-Apple Vision Pro

苹果以其在科技领域的创新而闻名&#xff0c;他们致力于推动技术的边界&#xff0c;这在他们的产品中表现得非常明显。他们尝试开发一项的新型突破性显示技术。在 2023 年 6 月 5 日官网宣布将发布 Apple Vision Pro 头戴空间设备&#xff0c;我们一起来了解一下 Apple Vision …...

cocos creator “TypeError: Cannot set property ‘string‘ of null

背景&#xff1a; 学习cocos creator时遇到"TypeError: Cannot set property string of null" 错误。具体代码如下&#xff1a;property({ type: Label })public stepsLabel: Label | null null;update(deltaTime: number) {this.stepsLabel.string Math.floor(…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...