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

数据结构--动态顺序表

文章目录

  • 线性表
  • 动态顺序表
    • 数组与顺序表
  • 接口实现
    • 初始化:
    • 尾插:
    • 尾删
    • 头插
    • 头删
    • 指定位置插入
    • 指定位置删除
    • 查找
    • 摧毁
  • 完整代码

线性表

线性表是数据结构中最基本、最简单也是最常用的一种数据结构。线性表是指由n个具有相同数据类型的元素组成的有限序列

线性表分为顺序表和链表两种实现方式。

  1. 顺序表
    顺序表是线性表的一种实现方式,它在计算机内存中以数组的形式保存数据元素。顺序表的特点是元素在内存中是连续存储的,通过索引可以直接访问元素,因此具有较快的随机访问速度。但是顺序表的长度是固定的,需要提前申请足够的内存空间,并且插入和删除元素时需要移动其他元素,效率较低。
    在这里插入图片描述

  2. 链表
    链表是线性表的另一种实现方式,它通过指针将多个节点串联起来。每个节点包含元素和指向下一个节点的指针,所以链表的内存分布可以是离散的。链表的优点是可以动态地分配内存,插入和删除操作只需要修改指针,效率较高。但是链表的访问速度比较慢,需要遍历节点找到目标位置。
    在这里插入图片描述

本章主要介绍的是顺序表。

动态顺序表

顺序表分为静态顺序表和动态顺序表;

静态顺序表是用定长数组来进行存储元素;
在这里插入图片描述
动态顺序表是利用动态存储开辟的数组:
在这里插入图片描述

数组与顺序表

顺序表和数组在某种程度上可以说是相似的,因为顺序表的基本实现就是数组。顺序表是对数组的一种封装,它在数组的基础上提供了更加灵活的内存管理方式,使得插入、删除等操作更加高效。

接口实现

我们要将函数都包含在一个头文件中,然后用一个源文件来对函数的实现;
结构

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTypeData;typedef struct SeqList
{SLTypeData* a;int size;  //有效个数int capacity;  //空间大小}SL;

初始化:

void SLInit(SL* ps)
{assert(ps);ps->a = (SLTypeData*)malloc(sizeof(SLTypeData) * 4);if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->size = 0;ps->capacity = 4;
}

对数组先开辟4个空间,然后判断是否开辟成功,成功就对size和容量进行初始化赋值;

尾插:

void AddCapacity(SL* ps)
{assert(ps);SLTypeData* cmp = (SLTypeData*)realloc(ps->a, sizeof(SLTypeData) * (ps->capacity + 3));if (cmp == NULL){perror("realloc failed");exit(-1);}ps->a = cmp;ps->capacity += 3;
}
void SLPushBack(SL* ps, SLTypeData x)
{//满需要扩容if (ps->size == ps->capacity){AddCapacity(ps);}//开始尾插ps->a[ps->size] = x;ps->size++;
}

在这里,由于还有头插和位置插入,所以就写一个函数来进行增加容量;每次容量增加3;尾插只需要在size下标进行赋值,最后再把size++即可;

我们写一个打印函数验证一下:

void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}

然后在主函数中加以验证:

#include"SeqList.h"int main()
{SL test;SLInit(&test);SLPushBack(&test, 1);SLPushBack(&test, 2);SLPushBack(&test, 3);SLPushBack(&test, 4);SLPushBack(&test, 5);SLPrint(&test);return 0;
}

在这里插入图片描述

尾删

void SLPopBack(SL* ps)
{assert(ps->size > 0);ps->size--;
}

验证:

int main()
{SL test;SLInit(&test);SLPushBack(&test, 1);SLPushBack(&test, 2);SLPushBack(&test, 3);SLPushBack(&test, 4);SLPushBack(&test, 5);SLPrint(&test);SLPopBack(&test);SLPrint(&test);return 0;
}

在这里插入图片描述

头插

void SLPushFront(SL* ps, SLTypeData x)
{assert(ps);//满扩容if (ps->size == ps->capacity){AddCapacity(ps);}//往后移for (int i = ps->size; i > 0; i--){ps->a[i] = ps->a[i-1];}//头插ps->a[0] = x;ps->size++;
}

这里要插入需要对当前数组进行挪移,给第一个元素腾出空间存储;

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);return 0;
}

在这里插入图片描述

头删

void SLPopFront(SL* ps)
{assert(ps);//判断assert(ps->size > 0);//左移for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}//size减1ps->size--;}

头一个元素删完之后,需要将后面元素向前移动;最后将size–;

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);SLPopFront(&test);SLPrint(&test);return 0;
}

在这里插入图片描述

指定位置插入

//起始位置为1,例如pos=1,那么就是在下标为0的位置插入
void SLInsert(SL* ps, int pos, SLTypeData x)
{assert(ps);assert(pos > 0 && pos <= ps->size + 1); //指定pos范围//满扩容if (ps->size == ps->capacity){AddCapacity(ps);}//位置后移for (int i = ps->size; i > pos - 1; i--){ps->a[i] = ps->a[i - 1];}//插入ps->a[pos - 1] = x;ps->size++;
}

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);SLInsert(&test, 3, 88);SLPrint(&test);return 0;
}

在这里插入图片描述

指定位置删除

void SLErase(SL* ps, int pos)
{assert(ps);assert(pos > 0 && pos <= ps->size);//指定pos范围//左移for (int i = pos - 1; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);SLInsert(&test, 3, 88);SLPrint(&test);SLErase(&test, 4);SLPrint(&test);return 0;
}

在这里插入图片描述

查找

查找对应的元素,如果有多个元素一样,返回的是最左边的元素;
返回的初始位置为1,例如下标为0,那么返回位置为1;

int SLFind(SL* ps, SLTypeData x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i+1;}}return -1;
}

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);int pos = SLFind(&test, 3);printf("3的位置是%d", pos);return 0;
}

在这里插入图片描述

摧毁

void SLDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}

验证:

int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);SLDestory(&test);SLPrint(&test);return 0;
}

在这里插入图片描述

完整代码

SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//动态顺序表
typedef int SLTypeData;typedef struct SeqList
{SLTypeData* a;int size;  //有效个数int capacity;  //空间大小}SL;void SLInit(SL* ps);//顺序表初始化
void SLDestory(SL* ps);//顺序表摧毁
void SLPushBack(SL* ps, SLTypeData x);//尾插
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps, SLTypeData x);//头插
void SLPopFront(SL* ps);//头删
int SLFind(SL* ps, SLTypeData x);//查找
void SLInsert(SL* ps, int pos, SLTypeData x);//插入
void SLErase(SL* ps, int pos);//删除
void SLPrint(SL* ps);//打印

SeqList.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLInit(SL* ps)
{assert(ps);ps->a = (SLTypeData*)malloc(sizeof(SLTypeData) * 4);if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->size = 0;ps->capacity = 4;
}void SLDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}//满扩容
void AddCapacity(SL* ps)
{assert(ps);SLTypeData* cmp = (SLTypeData*)realloc(ps->a, sizeof(SLTypeData) * (ps->capacity + 3));if (cmp == NULL){perror("realloc failed");exit(-1);}ps->a = cmp;ps->capacity += 3;
}
void SLPushBack(SL* ps, SLTypeData x)
{//满需要扩容if (ps->size == ps->capacity){AddCapacity(ps);}//开始尾插ps->a[ps->size] = x;ps->size++;
}void SLPopBack(SL* ps)
{assert(ps->size > 0);ps->size--;
}void SLPushFront(SL* ps, SLTypeData x)
{assert(ps);//满扩容if (ps->size == ps->capacity){AddCapacity(ps);}//往后移for (int i = ps->size; i > 0; i--){ps->a[i] = ps->a[i-1];}//头插ps->a[0] = x;ps->size++;
}void SLPopFront(SL* ps)
{assert(ps);//判断assert(ps->size > 0);//左移for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}//size减1ps->size--;}int SLFind(SL* ps, SLTypeData x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i+1;}}return -1;
}void SLInsert(SL* ps, int pos, SLTypeData x)
{assert(ps);assert(pos > 0 && pos <= ps->size + 1);//满扩容if (ps->size == ps->capacity){AddCapacity(ps);}//位置后移for (int i = ps->size; i > pos - 1; i--){ps->a[i] = ps->a[i - 1];}//插入ps->a[pos - 1] = x;ps->size++;
}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos > 0 && pos <= ps->size);assert(pos > 0);//左移for (int i = pos - 1; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");}

test.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"int main()
{SL test;SLInit(&test);SLPushFront(&test, 1);SLPushFront(&test, 2);SLPushFront(&test, 3);SLPushFront(&test, 4);SLPushFront(&test, 5);SLPrint(&test);SLDestory(&test);SLPrint(&test);return 0;
}

相关文章:

数据结构--动态顺序表

文章目录 线性表动态顺序表数组与顺序表 接口实现初始化&#xff1a;尾插&#xff1a;尾删头插头删指定位置插入指定位置删除查找摧毁 完整代码 线性表 线性表是数据结构中最基本、最简单也是最常用的一种数据结构。线性表是指由n个具有相同数据类型的元素组成的有限序列。 线…...

笔试数据结构选填题

目录 卡特兰数Catalan&#xff1a;出栈序列/二叉树数 树 二叉树 N01N2 哈夫曼树&#xff08;最优二叉树&#xff09;Huffman 度m的哈夫曼树只有度为0和m的结点&#xff1a;Nm(n-1)/(m-1) 平衡二叉树AVL Nh表示深度为h最少结点数&#xff0c;则N00&#xff0c;N11&#…...

# 鸢尾花的案例学习

# 鸢尾花的案例学习 # 1. 导入小型的数据 from sklearn.datasets import load_iris import numpy as np import pandas as pd import seaborn as sbn import matplotlib.pyplot as plt # 2. 获取数据 irisload_iris() # 3.查看数据print("数据集\n ",len(iris.d…...

线程、进程的区别

线程、进程的区别 在开发中&#xff0c;我们经常听到线程和进程两个概念&#xff0c;它们都是操作系统的基本概念&#xff0c;操作系统以进程为基本单位分配存储器&#xff0c;以线程为基本单位分配CPU。虽然它们有很多相似之处&#xff0c;但是它们也有很大的区别。本文将详细…...

在 Ubuntu 上安装 Docker 桌面

Ubuntu 22.04 (LTS) 安装 Docker 桌面 要成功安装 Docker Desktop&#xff0c;您必须&#xff1a; 满足系统要求拥有 64 位版本的 Ubuntu Jammy Jellyfish 22.04 (LTS) 或 Ubuntu Impish Indri 21.10。对于非 Gnome 桌面环境&#xff0c;必须安装 gnome-terminal&#xff1a;…...

【WebRTC---序篇】(七)RTC多人连麦方案

服务端可以选择mediasoup&#xff0c;作为SFU服务器&#xff0c;只负责转发数据 下图举例三个Client (browser或者客户端)同时加入一个房间&#xff0c;每个app同时发布一路视频和一路音频&#xff0c;并且接受来自其他app的音视频流&#xff0c;mediasoup内部的结构如下&…...

【Java可执行命令】(十六)诊断命令请求发送工具 jcmd:提供一种简单而强大的方式来管理和监控 Java 进程 ~

Java可执行命令之jcmd 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 jcmd -l&#xff1a;列出正在运行的 Java 进程3.3 jcmd < pid> help&#xff1a;列出特定进程的诊断命令列表3.4 jcmd < pid> < command>&#xff1a;执行诊断命令 4️⃣ 应用场景…...

如何创建无序列表和有序列表?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 无序列表⭐ 无序列表⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴…...

【MongoDB】初识、安装MongoDB

目录 一、MongoDB主要应用场景 二、MongoDB简介 三、MongoDB相关特点 四、MongoDB的安装 一、MongoDB主要应用场景 传统的数据库如MySQL在应对三高场景时显得力不从心 三高&#xff1a; High performance 对数据库高并发读写的需求 High Storage 对海量数据的高效率存储和 …...

方法区内存溢出及常量池

22 方法区-定义 是所有线程共享的一块区域。 存储了和类结构相关信息。运行时常量池&#xff0c; 方法区在虚拟机启动时被创建&#xff0c;逻辑上是堆的组成部分。方法区内存不足&#xff0c;也会导致oom异常。 是一个概念上的东西&#xff0c; 1.6使用永久代作为方法区&#…...

【MTK平台】【wpa_supplicant】关于wpa_supplicant_8/src/p2p/p2p_invitation.c文件的介绍

本文主要介绍external/wpa_supplicant_8/src/p2p/p2p_invitation.c文件 这里主要介绍6个方法 1.p2p_invite //p2p邀请调用此方法 2.p2p_invite_send //对p2p_invite方法进行补充 3. p2p_process_invitation_resp 4.p2p_process_invitation_req 5.p2p_build_invitation_re…...

智能仪表板DevExpress Dashboard v23.1亮点 - 增强对自定义导出的支持

DevExpress Dashboard v23.1版本增强了自定义导出到Excel的功能等&#xff0c;欢迎下载最新版本体验&#xff01; DevExpress Dashboard v23.1正式版下载(Q技术交流&#xff1a;523159565&#xff09; 所有平台 导出自定义仪表板项目到Excel 用户现在可以在WinForms和Web应…...

分布式应用:ELK企业级日志分析系统

目录 一、理论 1.ELK 2.ELK场景 3.完整日志系统基本特征 4.ELK 的工作原理 5.ELK集群准备 6.Elasticsearch部署&#xff08;在Node1、Node2节点上操作&#xff09; 7.Logstash 部署&#xff08;在 Apache 节点上操作&#xff09; 8.Kiabana 部署&#xff08;在 Node1 节点…...

Mac与windows传文件(超过4G且速度超快,非共享)

MAC与Windows文件互传 背景 尝试了网上的一些方法&#xff0c;诸如设置共享文件夹方法等&#xff0c;但是实际使用中感觉效果一般&#xff0c;对于一些小的文件共同编辑速度还可以。但是在备份或者传递一些较大文件或者很多细小文件的时候就有点捉襟见肘了。制作了一个MAC可读…...

2023年第四届“华数杯”数学建模思路 - 案例:退火算法

## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 退火算法原理 1.1 物理背景 在热力学上&#xff0c;退火&#xff08;annealing&#xff09;现象指物体逐渐降温的物理现象&#xff0c;温度愈低&#…...

STM32 UDS Bootloader开发-上位机篇-CANoe制作(3)

文章目录 前言刷写脚本34服务写入数据的实现定时函数writeBlockData函数Checksum总结前言 上一篇文章中介绍了CAPL刷写脚本的大部分内容,本文继续介绍34,36,37服务的实现,及checksum中遇到的坑 刷写脚本 34服务 void requestDownLoad(struct Block hexfile) {gTxBuffer[…...

GO语言的垃圾回收机制

内存垃圾的产生 程序在内存上被分为堆区、栈区、全局数据区、代码段、数据区五个部分。对于C等早期编程语言栈上的内存回由编译器负责管理回收&#xff0c;而堆上的内存空间需要编程人员负责申请和释放。在Go中栈上内存仍由编译器负责管理回收&#xff0c;而堆上的内存由编译器…...

vim粘贴内容格式混乱解决方法

问题 复制本地文件内容后&#xff0c;咱贴到vim文本内&#xff0c;格式错乱 解决方法 打开vim配置文件 最后面加入一行 vim /etc/vimrc set pastetoggle<F11> 开发vim文件&#xff0c;进入后先按F11进入交互模式 shift insert 再次粘贴 解决...

基于Orangepi 3 lts 的云台相机

利用orangepi 3 lts 和arduino nano 制作了一个云台相机&#xff0c;可用于室内监控。 硬件&#xff1a; orangepi 3 ,arduino nano ,usb相机&#xff0c;180度舵机两个 WeChat_20230806213004 软件&#xff1a; 整体采用mqtt进行消息的中转。 相机采用python 利用opencv…...

Go重写Redis中间件 - Go实现Redis持久化

GO实现Redis持久化 项目开发到这里,我们的下一步就是实现Redis的持久化落盘功能,Redis是一个内存型的数据库,在之前我们实现的单机版Redis如果把进程杀掉,我们通过GET、SET指令存储的数据都将不复存在,数据只存在内存的map里面,重启之后什么都没有了 我们现在的目标就是…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...