01数据结构 - 顺序表

news2024/9/22 21:13:33

这里是只讲干货不讲废话的炽念,这个系列的文章是为了我自己以后复习数据结构而写,所以可能会用一种我自己能够听懂的方式来描述,不会像书本上那么枯燥和无聊,且全系列的代码均是可运行的代码,关键地方会给出注释^_^

全文近8000字

版本:C++17

编译器:Clion 2023.3.24

暂时只给出代码,不会涉及到基础知识的讲解

1.线性表的定义

//定义顺序表的表头结构
typedef struct {
    Element* data;              // 指向顺序表的数据区域
    int len;                    // 该区域能够访问的边界条件,目前内容器存储数据的数量
    int cap;                    // 该区域最大容量,超过这个容量就需要扩容
}SeqList;

2.线性表的实现函数

2.1.表的创建以及删除

// 表的创建以及删除
SeqList *createSeqList(int n);                  // 创造一个表并初始化

void releaseSeqList(SeqList *seqList);          // 释放掉表头以及表内的数据

 

 2.2.扩容函数

// 辅助函数
int enLargerSeq(SeqList *seqList);                  // 扩容函数

 

2.3.向表中插入元素

// 三种插入方式
int pushBackSeq(SeqList *seqList, Element val);         // 往尾部插入一个元素

int headInsertSeq(SeqList *seqList, Element val);       // 往头部插入一个元素

int insertSeq(SeqList *seqList, int pos, Element val);  // 按指定值来插入元素

 

2.4.表的展示以及查找

// 展示以及查找
void showSeqList(SeqList *seqList);                // 遍历并显示数据

int findSeq(SeqList *seqList, Element val);        // 按值查找

 

2.5.删除表中的元素

// 三种方式删除
int deleteSpeSeq(SeqList *seqList, Element val);   // 删除特定值的元素

int deleteHeadSeq(SeqList *seqList);               // 删除首元素

int deleteTailSeq(SeqList *seqList);               // 删除尾元素

3.实现函数的代码

3.1.createSeqList函数的实现

函数定义:
SeqList *createSeqList(int n);                  // 创造一个表并初始化

 

函数功能:
该函数用于创建一个长度为n的顺序表,并返回指向该顺序表的指针

 

实现方法
a.申请表头空间

b.申请表内元素的空间

c.初始化 len(length 长度) 和 cap(capacity 容量)

d.对申请的空间进行检查,如果申请空间失败,则需要返回NULL

 

具体实现代码:
SeqList *createSeqList(int n) {
    SeqList *seqList;
    seqList = (SeqList *)malloc(sizeof(SeqList));               //申请表头
    if (seqList == NULL){
        printf("Malloc seqlist failed\n");
        return NULL;
    }

    seqList->data = (Element *) malloc(sizeof(Element) * n);    //申请空间
    if (seqList->data == NULL){
        printf("Malloc data failed");
        return NULL;
    }

    seqList->len = 0;
    seqList->cap = n;

    return seqList;
}

 

测试代码:
int main() {
    SeqList *list = createSeqList(10);
    if (list == NULL) {
        printf("创建顺序表失败\n");
        return 1;
    }
    printf("顺序表创建成功\n");
    free(list->data);
    free(list);

    return 0;
}

 

测试结果:

3.2 releaseSeqList函数的实现

函数定义:
void releaseSeqList(SeqList *seqList);          // 释放掉表头以及表内的数据

 

函数功能:
该函数用于释放一个顺序表所占用的内存空间,防止内存泄漏

 

实现方法:
a.先判断表头再判断数据域是否为空

b.如果数据域不为空,则释放掉表内的数据域空间

c.释放掉表头空间

 

 具体实现代码:
void releaseSeqList(SeqList *seqList) {
    if (seqList){
        if (seqList->data){
            free(seqList->data);
        }
        free(seqList);
        printf("Release success!\n");
    }
}

 

测试代码:
int main() {
    SeqList *list = createSeqList(10);
    if (list == NULL) {
        printf("创建顺序表失败\n");
        return 1;
    }
    printf("顺序表创建成功\n");

    releaseSeqList(list);  // 释放顺序表

    return 0;
}

 

测试结果:

3.3 enLargerSeq 函数的实现

函数定义:
int enLargerSeq(SeqList *seqList);                  // 扩容函数

 

函数功能:
该函数用于对顺序表进行扩容,将顺序表的大小扩展为原来的两倍

 

实现方法:
a.先申请一个新空间 tmp,新空间的大小为原来空间大小(seqList->len / seqList->cap)的两倍
b.将原来空间的值通过 for 循环赋值给新空间
c.释放掉原来表头指向的空间 seqList->data
d.将表头的 seqList->data 指向新申请的空间 tmp
e.将 seqList->cap 大小变为原来的两倍

 

具体实现代码:
int enLargerSeq(SeqList *seqList) {
    Element *tmp = (Element *) malloc(sizeof (Element) * 2 * seqList->cap);
    if (!tmp){
        printf("Enlarger element failed!\n");
        return -1;
    }

    for (int i = 0; i < seqList->len; i++){
        tmp[i] = seqList->data[i];
    }

    free(seqList->data);    // 这两句是否有先后?
    seqList->data = tmp;    // 有先后,如果调换顺序就会先指向新的内存空间,然后再释放老的内存空间,此时老的内存空间已经找不到了,会发生内存泄露
    seqList->cap *= 2;
    printf("Enlarge success!\n");
    return 0;
}

 

测试代码:
int main(){
    SeqList *list = createSeqList(5);
    for (int i = 0; i < 5; i++){
        pushBackSeq(list, i);
    }

    pushBackSeq(list,666);
    showSeqList(list);
    printf("%d", list->cap);
    return 0;
}

 

测试结果:

3.4 showSeqList && findSeq 函数的实现

函数定义:
void showSeqList(SeqList *seqList);                // 遍历并显示数据

int findSeq(SeqList *seqList, Element val);        // 按值查找

 

函数功能:

1.showSeqList 函数

该函数用于遍历并显示顺序表中的所有数据

2.findSeq 函数 

该函数用于在顺序表中查找指定的值,并返回该值的索引。如果未找到,则返回 -1

 

实现方法:

1.showSeqList 函数

a.首先判断传入的表是否为空
b.使用 for 循环遍历整个表并打印数据

2.findSeq 函数

a.判断传染的表是否为空且表的长度是否合法(seqList->len > 0)
b.使用for循环遍历表,如果找到了val就直接返回该数的下标
c.如果没找到,打印提示信息,返回-1

 

具体实现代码:
// showSeqList 函数
void showSeqList(SeqList *seqList) {
    if (seqList == NULL || seqList->data == NULL){
        printf("SeqList is null.Show error\n");
        return;
    }
    for (int i = 0; i < seqList->len; i++){
        printf("%d ", seqList->data[i]);
    }
    printf("\n");
}

// findSeq 函数
int findSeq(SeqList *seqList, Element val) {
    if (!seqList || !seqList->data || seqList->len <= 0){
        printf("SeqList is null!\n");
        return -1;
    }

     for (int i = 0; i < seqList->len; i++){
         if (seqList->data[i] == val){
             return i;
         }

     }

     printf("Find value error!\n");
     return -1;
}

 

测试代码:
int main(){
    SeqList *list = createSeqList(5);
    for (int i = 0; i < 5; i++){
        pushBackSeq(list, i);
    }

    showSeqList(list);

    int index1 = findSeq(list, 666);
    int index2 = findSeq(list,0);
    printf("%d\n", index1);
    printf("%d\n", index2);

    releaseSeqList(list);
    return 0;
}

 

测试结果:

3.4 pushBackSeq && headInsertSeq && insertSeq 函数的实现

函数定义:
int pushBackSeq(SeqList *seqList, Element val);         // 往尾部插入一个元素

int headInsertSeq(SeqList *seqList, Element val);       // 往头部插入一个元素

int insertSeq(SeqList *seqList, int pos, Element val);  // 按指定位置来插入元素

 

函数功能:
1.pushBackSeq 函数
在顺序表尾部插入一个元素
2.headInsertSeq 函数
在顺序表头部插入一个元素
3.insertSeq 函数
在顺序表指定位置插入一个元素

 

实现方法:

1.pushBackSeq 函数

a.判断传入的链表以及数据域是否为空

b.判断当前元素是否到达空间上限,如果是则需要扩容

c.往 seqList->len 的位置放入元素

d.seqList->len++

 2.headInsertSeq 函数

a.判断传入的链表以及数据域是否为空

b.判断当前元素是否到达空间上限,如果是则需要扩容

c.从第 1 个元素开始,依次往后移动元素

d.往下标为 0 的位置放入元素

e.seqList->len++

3.insertSeq 函数

a.判断传入的链表以及数据域是否为空

b.判断当前元素是否到达空间上限,如果是则需要扩容

c1.从第 pos+1 个元素开始,依次往后移动元素
c2.从第 seqList->len-1 个元素开始,直到第 pos 个元素(包含),从后往前移动元素

d.往下标为 pos 的位置放入元素

e.seqList->len++

 

具体实现代码:

1.pushBackSeq 函数

// pushBackSeq 函数
int pushBackSeq(SeqList *seqList, Element val) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null");
        return -1;
    }

    if (seqList->len >= seqList->cap){
        printf("Insertion overflow. Consider enlarging the structure!\n");
        if (enLargerSeq(seqList) == -1){
            printf("Enlarge failed!\n");
            return -1;
        }
    }

    seqList->data[seqList->len] = val;
    seqList->len++;

    return 0;
}

  2.headInsertSeq 函数

// headInsertSeq 函数
int headInsertSeq(SeqList *seqList, Element val) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null");
        return -1;
    }

    if (seqList->len >= seqList->cap){
        printf("Insertion overflow. Consider enlarging the structure!\n");
        if (enLargerSeq(seqList) == -1){
            printf("Enlarge failed!\n");
            return -1;
        }
    }

    for (int i = seqList->len; i > 0; i--) {        // 核心移动逻辑
        seqList->data[i] = seqList->data[i-1];
    }

    seqList->data[0] = val;
    seqList->len++;
    return 0;
}

 3.insertSeq 函数

// insertSeq 函数
int insertSeq(SeqList *seqList, int pos, Element val) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null");
        return -1;
    }

    if (pos < 0 || pos > seqList->len){
        printf("Insert value out of bounds\n");
        return -1;
    }

    if (seqList->len >= seqList->cap){
        printf("Insertion overflow. Consider enlarging the structure!\n");
        if (enLargerSeq(seqList) == -1){
            printf("Enlarge failed!\n");
            return -1;
        }
    }
    
    for (int i = seqList->len-1; i >= pos; i--){    // 核心移动逻辑
        seqList->data[i+1] = seqList->data[i];
    }

    seqList->data[pos] = val;
    seqList->len++;

    return 0;
}

 

测试代码:
int main(){
    SeqList *list = createSeqList(5);
    for (int i = 0; i < 5; i++){
        pushBackSeq(list, i);
    }

    showSeqList(list);

    insertSeq(list, 5, 111);      // 任意位置插入
    showSeqList(list);

    insertSeq(list, 0, 222);      // 任意位置插入
    showSeqList(list);

    insertSeq(list, 999, 333);    // 任意位置插入
    showSeqList(list);
    printf("\n");

    headInsertSeq(list, 888);     // 头插法
    showSeqList(list);

    printf("\n");
    pushBackSeq(list, 666);       // 尾插法
    showSeqList(list);

    releaseSeqList(list);
    return 0;
}

 

测试结果:

 

 

3.5 deleteSpeSeq && deleteHeadSeq && deleteTailSeq 函数的实现

函数定义:
int deleteSpeSeq(SeqList *seqList, Element val);   // 删除特定值的元素

int deleteHeadSeq(SeqList *seqList);               // 删除首元素

int deleteTailSeq(SeqList *seqList);               // 删除尾元素

 

函数功能:

1.deleteSpeSeq 函数

该函数用于在顺序表中删除指定值的元素

2. deleteHeadSeq 函数  

该函数用于删除顺序表中的首元素

 3.deleteTailSeq 函数 

该函数用于删除顺序表中的尾元素

 

实现方法:

1.deleteSpeSeq 函数

a.判断传入的表是否为空
b.调用 findSeq 函数,判断要查找的值是否在表中
c.如果不在表中,则返回错误标志
d.从 pos+1 的位置开始,从后往前覆盖元素
e.seqList->len--

2. deleteHeadSeq 函数 

a.判断传入的表是否为空
b.判断表内是否有元素
c.从第二个元素(索引为1)开始,从后往前进行覆盖
d.seqList->len--

3.deleteTailSeq 函数 

a.判断传入的表是否为空
b.判断表内是否有元素
d.seqList->len--

 

具体实现代码:

1.deleteSpeSeq 函数

int deleteSpeSeq(SeqList *seqList, Element val) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null. Delete failed!\n");
        return -1;
    }

    int pos = findSeq(seqList, val);
    if (pos == -1){
        printf("Delete value error!\n");
        return -1;
    }
    
    for (int i = pos + 1; i < seqList->len; i++){
        seqList->data[i - 1] = seqList->data[i];
    }
    /*for (int i = pos; i < seqList->len; i++){ // 第二种写法可能会有溢出的风险
        seqList->data[i] = seqList->data[i + 1];
    }*/

    seqList->len--;

    return 0;
}

2. deleteHeadSeq 函数

int deleteHeadSeq(SeqList *seqList) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null. Delete failed!\n");
        return -1;
    }

    if (seqList->len <= 0){
        printf("Delete head value failed!");
        return -1;
    }

    for (int i = 1; i < seqList->len; i++){
        seqList->data[i-1] = seqList->data[i];
    }

    seqList->len--;
    return 0;
}

3.deleteTailSeq 函数

int deleteTailSeq(SeqList *seqList) {
    if (!seqList || !seqList->data){
        printf("Seqlist is null. Delete failed!\n");
        return -1;
    }

    if (seqList->len <= 0){
        printf("Delete tail value failed!");
        return -1;
    }

    seqList->len--;

    return 0;
}

 

测试代码:
int main(){
    SeqList *list = createSeqList(5);
    for (int i = 0; i < 5; i++){
        pushBackSeq(list, i);
    }

    deleteHeadSeq(list);
    showSeqList(list);

    deleteTailSeq(list);
    showSeqList(list);

    deleteSpeSeq(list,999);
    showSeqList(list);

    deleteSpeSeq(list,1);
    showSeqList(list);

   
    releaseSeqList(list);
    return 0;
}

 

测试结果:

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

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

相关文章

CSS-0_3 CSS和单位

文章目录 CSS的值和单位属性值长度单位CSS和绝对单位CSS和相对单位百分比em & rem视口 颜色单位 碎碎念 CSS的值和单位 我们知道&#xff0c;CSS是由属性和属性值所组成的表 随着CSS的发展&#xff0c;属性不说几千也有几百&#xff0c;我从来不支持去背诵所有的可能性。…

AWS Aurora Postgres 的开源替代品:存储和计算分离 | 开源日报 No.278

neondatabase/neon Stars: 13.0k License: Apache-2.0 Neon 是一个无服务器的开源替代品&#xff0c;用于 AWS Aurora Postgres。它将存储和计算分离&#xff0c;通过在节点集群中重新分配数据来替换 PostgreSQL 存储层。 提供自动扩展、分支和无限存储。Neon 安装包括计算节…

图解PyTorch中的Transpose操作

在PyTorch中&#xff0c;我们时常会对张量进行转置操作。若张量是二维的&#xff0c;则非常容易理解。若张量维度更高&#xff0c;则会令人摸不到头脑。 高维张量究竟是怎么转置的&#xff1f;简单来说&#xff0c;就是将参与转置的维度抽出来&#xff0c;将内侧的子张量视为一…

设计模式学习(二)工厂模式——抽象工厂模式

设计模式学习&#xff08;二&#xff09;工厂模式——抽象工厂模式 背景抽象工厂模式优点与缺点参考文章 背景 现在我需要开发一个相机操作模块&#xff0c;它可能在Windows下运行&#xff0c;也可能在Linux下运行。由于在厂家提供的SDK中&#xff0c;Windows下的SDK和Linux下…

DROO论文笔记

推荐文章DROO源码及论文学习 读论文《Deep Reinforcement Learning for Online Computation Offloading in Wireless Powered Mobile-Edge Computing Networks》的笔记 论文地址&#xff1a;用于无线移动边缘计算网络在线计算卸载的深度强化学习 论文代码地址&#xff1a;DR…

统计学9——分类数据统计

知识结构 内容精读 1.分类数据与$\chi^2$统计量 分类数据在第一章已经进行了详细介绍&#xff0c;就是对数据进行分类的结果&#xff0c;特征是&#xff0c;调查结果虽然用数值表示&#xff0c;但不同数值描述了调查对象的不同特征。由此分类数据的结果是频数&#xff0c;而$…

git链接远程仓库

【 一 】ssh链接远程仓库 删除git仓库 【 1 】初步使用方法 1、之前把本地代码&#xff0c;以https形式&#xff0c;提交到了远程仓库 # - git remote add origin https://gitee.com/bai-zhitao/lufy.git- 输入用户名密码2、ssh认证&#xff0c;只需要配置一次&#xff…

uniapp踩坑之项目:uni-table垂直居中和水平居中

uni-table 中的水平居中uni-td align"center"&#xff0c;css里的属性vertical-align: middle //html 水平居中<uni-table ref"table" :loading"loading" border stripe emptyText"暂无更多数据"><uni-tr><uni-th :wid…

车载音视频MediaPlayer优化方案

媒体播放现状 从手机到车载&#xff0c;在很多地方还是有很大的不同。针对多媒体的场景Android车机目前大部分结构大致结构如下图&#xff1a; 从以上图看出的问题&#xff1a; 各个音视频APP单独实现播控界面&#xff0c;播放链路不一致&#xff0c;使用的底层播放器和音频焦…

JavaEE:Spring Web简单小项目实践二(用户登录实现)

学习目的&#xff1a; 1、理解前后端交互过程 2、学习接口传参&#xff0c;数据返回以及页面展示 1、准备工作 创建SpringBoot项目&#xff0c;引入Spring Web依赖&#xff0c;添加前端页面到项目中。 前端代码&#xff1a; login.html <!DOCTYPE html> <html lang&…

云备份服务端

文件使用工具和json序列化反序列化工具 //文件和json工具类的设计实现 #ifndef __UTIL__ #define __UTIL__ #include<iostream> #include<fstream> #include<string> #include <vector> #include<sys/stat.h> #include"bundle.h" #inc…

68、Flink DataStream Connector 之文件系统详解

文件系统 1.概述 连接器提供了 BATCH 模式和 STREAMING 模式统一的 Source 和 Sink。 Flink FileSystem abstraction支持连接器对文件系统进行&#xff08;分区&#xff09;文件读写&#xff0c;文件系统连接器为 BATCH 和 STREAMING 模式提供了相同的保证&#xff0c;而且对…

数字孪生Digital Twin 结合建筑信息模型 BIM 在AIoT 智慧城市建设中Web 可视化大屏实践...

智慧城市建设通过将城市中的建筑、基础设施等构建 BIM 模型&#xff0c;并与实时采集的数据相结合&#xff0c;创建数字孪生体。可以实现对城市能源消耗、交通流量、环境质量等的实时监测和预测&#xff0c;优化城市规划和资源分配。 01 数字孪生 Digital Twin 数字孪生 Digita…

Spring MVC 全注解开发

1. Spring MVC 全注解开发 文章目录 1. Spring MVC 全注解开发2. web.xml 文件 的替代2.1 Servlet3.0新特性2.2 编写 WebAppInitializer 3. Spring MVC的配置3.1 Spring MVC的配置&#xff1a;开启注解驱动3.2 Spring MVC的配置&#xff1a;视图解析器3.3 Spring MVC的配置&…

【实战:python-Django发送邮件-短信-钉钉通知】

一 Python发送邮件 1.1 使用SMTP模块发送邮件 import smtplib from email.mime.text import MIMEText from email.header import Headermsg_from 306334678qq.com # 发送方邮箱 passwd luzdikipwhjjbibf # 填入发送方邮箱的授权码(填入自己的授权码&#xff0c;相当于邮箱…

SSE、Webworker 、webSocket、Http、Socket 服务器推送技术

Http协议 受浏览器的同源策略限制 HTTP 协议是一种无状态的、无连接&#xff08;短暂连接&#xff0c;客户端发送请求&#xff0c;服务器响应后即断开连接&#xff09;的、单向的应用层协议。 它采用了请求/响应模型。通信请求只能由客户端发起&#xff0c;服务端对请求做出应…

(day18) leetcode 204.计数质数

描述 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 示例 1&#xff1a; 输入&#xff1a;n 10 输出&#xff1a;4 解释&#xff1a;小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。示例 2&#xff1a; 输入&#xff1a;n 0 输出&#xff1a;0示例 3…

JVM--自动内存管理--JAVA内存区域

1. 运行时数据区域 灰色的线程共享&#xff0c;白色的线程独享 白色的独享就是根据个体"同生共死" 程序计数器&#xff1a; 是唯一一个没有OOM(内存溢出)的地方 是线程独享的 作用&#xff1a; 是一块较小的内存空间,是当前线程所执行的字节吗的行号指示器 由于…

智慧水利:迈向水资源管理的新时代,结合物联网、云计算等先进技术,阐述智慧水利解决方案在提升水灾害防控能力、优化水资源配置中的关键作用

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…

docker 安装 onlyoffice

1.文档地址 Installing ONLYOFFICE Docs for Docker on a local server - ONLYOFFICE 2.安装onlyoffice docker run -i -t -d -p 9000:8000 --restartalways -e JWT_ENABLEDfalse onlyoffice/documentserver 如果发现镜像无法下载,可以尝试更换镜像源 {"registry-mir…