数据结构(初阶2.顺序表)

文章目录

一、线性表

二、顺序表

 2.1 概念和结构

 2.2 分类

    2.2.1 静态顺序表

    2.2.2 动态顺序表

 2.3动态顺序表的实现

  1.SeqList.h

  2.SeqList.c

    打印顺序表

    初始化

    销毁

    增容

    尾插

    头插

    在指定位置之前插入数据

    尾删

    头删

    在指定位置删除数据

  3.test.c


一、线性表

线性表( linear list )是n个具有相同特性的数据元素的有限序列。
线性表是⼀种在实际中⼴泛使⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。
  • 逻辑结构(认为想象出来的数据的组织形式):都是线性的
  • 物理结构(数据在内存上的存储形式):不一定是线性的

二、顺序表

2.1 概念和结构

概念:顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采⽤数组存储。
那么数组和顺序表的区别是什么?
下面可以进行一个很形象的类比:
  • 顺序表是对数组进行封装:结构体
  • 定义已经知道数组的大小:    int arr【3】= {1,2,3};
  • 定义未知道数组的大小:        int*arr;

2.2 分类

2.2.1 静态顺序表

上图中可以发现我们重新定义了 typedef int SLDataType,为什么?

比如当我们在测试代码中有 100000行代码,1000+会定义整型变量 int,当要把这 1000+ 的代码部分改成 char 类型时,如果逐个将这些代码找出一句句修改会非常麻烦而且工作量巨大;             

而当 typedef int SLDataType之后 ,我们只需将其改成 typedef char SLDataType ,遍能一键替换为 char 或者想要修改的位置。

2.2.2 动态顺序表

2.3动态顺序表的实现

(注意:1.当我们每实现一个方法之后须测试一下,切记写完所有方法才测试,避免出现差错;

             2.在调用过程中分清传值和传址的区别;

                传值:形参是实参的值的拷贝,实参和形参指向的是两块不同的地址,但保存的数据是一样的

                传址:形参指向的是实参指向的地址) 

1.SeqList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义动态顺序表结构
typedef int SLDatatype;typedef struct SeqList {SLDatatype* arr;int capacity; //空间大小int size;     //有效数据个数
}SL;//typedef struct SeqList SL;//初始化
void SLInit(SL* ps);
//销毁
void SLDestroy(SL* ps);//打印顺序表
void SLPrint(SL* ps);//插入数据
void SLPushBack(SL* ps, SLDatatype x);
void SLPushFront(SL* ps, SLDatatype x);//删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//在指定位置之前插入数据
void SLInsert(SL* ps, SLDatatype x, int pos);
//删除指定位置的数据
void SLErase(SL* ps, int pos);

2.SeqList.c 

  • 打印顺序表
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
  • 初始化  
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
  • 销毁
void SLDestory(SL* ps)
{if (ps->arr != NULL){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
  •  增容

当size == capacity 时,说明顺序表满了,空间不足,先增容,再插入;

增容一般是成倍数的增加(增容的操作本身就有一定的程序性能的消耗,若频繁的增容会导致程序效率底下),所以 ”一次增容一个就没有空间浪费“ 这种说法是错误的。 

增容分两种情况: 1.连续空间足够,直接扩容 

                              2.连续空间不够,1)重新找一块地址,分配足够的内存 

                                                          2)拷贝数据到新的地址 

                                                          3)销毁旧地址 

void SLCheckCapacity(SL* ps)
{//判断空间是否充足if (ps->size = ps->capacity){//增容//0*2 = 0//若capacity为0,给个默认值,否则×2倍int newCapacity = ps->arr == 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;}
}
  • 尾插 

空间充足:将数据插入 size 指向的位置,size++;

void SLPushBack(SL* ps, SLDatatype x)
{assert(ps);//等价于assert(ps != NULL)SLCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}
  • 头插
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];}//将数据插入下标为0的位置ps->arr[0] = x;
}
  • 在指定位置之前插入数据
void SLInsert(SL* ps, SLDatatype x, int pos)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//       头插          尾插 //pos及以后的数据整体向后移动一位,从后往前移,与头插的方法类似for (int i =ps->size ; i>pos; i--){ps->arr[i] = ps->arr[i - 1];}//将数据插入下标为pos的位置ps->arr[pos] = x;ps->size++; //不要忘记这一步
}
  • 尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//顺序表为空,不可删除ps->size--;
}
  • 头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//顺序表为空,不可删除//数据整体向前移动一位,从前往后移for (int i = 0; i < ps->size - 1;i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}
  • 在指定位置删除数据
void SLDelete(SL* ps, int pos)
{assert(ps);assert(ps->size);//顺序表为空,不可删除assert(pos >= 0 && pos < ps->size);//       头删          尾删 //pos及以后的数据整体向前移动一位,从前往后移,与SLInsert的方法类似for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

 3.test.c

#include "SeqList.h"void SLtest01()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 10);SLPushBack(&s, 11);SLPushBack(&s, 12);printf("尾插后的数据:");SLPrint(&s);printf("头插后的数据:");SLPushFront(&s, 4);SLPrint(&s);printf("在下标为2的位置插入9后的数据:");SLInsert(&s, 9, 2);SLPrint(&s);printf("尾删后的数据:");SLPopBack(&s);SLPrint(&s);printf("头插后的数据:");SLPopFront(&s);SLPrint(&s);printf("删除下标为3的数据:");SLDelete(&s, 3);SLPrint(&s);SLDestroy(&s);
}int main()
{SLtest01();	return 0;
}

未完待续~~

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

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

相关文章

如何解决VMware 安装Windows10系统出现Time out EFI Network...

一、问题描述 使用VMware 17 安装windows10出现如下图所示Time out EFI Network… Windows10镜像为微软官方下载的ISO格式镜像&#xff1b; 二、问题分析 VMware 17 默认的固件类型是UEFI(E)&#xff0c;而微软官网下载的Windows10 ISO格式镜像不支持UEFI(E)&#xff0c;支…

【中项第三版】系统集成项目管理工程师 | 第 4 章 信息系统架构④ | 4.7

前言 第4章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术相关的内容&#xff0c;学习要以教材为准。本章分值预计在4-5分。 目录 4.7 安全架构 4.7.1 安全威胁 4.7.2 定义与范围 4.7.3 整体架构设计 4.7.4 网络安全架构设计 4.7.5 数据库系统安…

C++基础语法:STL之迭代器

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 C基础:STL概述-CSDN博客 上一篇梳理了一些同STL有关的概念.同时对理解迭代器需要的类包含,内部类,链表等内容做了分析,这篇从<C Prime Plus> 6th Edition(以下称"本书")的P684,大标题16.4泛型编…

C++继承和多态

目录 继承 继承的意义 访问限定符、继承方式 赋值兼容规则&#xff08;切片&#xff09; 子类的默认成员函数 多继承 继承is a和组合has a 多态 什么是多态 形成多态的条件 函数重载&#xff0c;隐藏&#xff0c;重写的区别 override和final 多态原理 继承 继承的…

Algorithms,最全的Python算法仓库!

学习编程、学习Python最好的方式就是练习&#xff0c;哪怕是新手&#xff0c;只要不断地敲代码输出&#xff0c;肯定会有神效。 Python的练手项目很多&#xff0c;特别是Github上&#xff0c;建议不管新手、老司机都去看看。 这里推荐给大家一个Gitthub上练习的项目&#xff…

高级Puppet manifest编写和模块化管理:构建高效可靠的自动化运维平台

高级Puppet manifest编写和模块化管理&#xff1a;构建高效可靠的自动化运维平台 Puppet是一种流行的开源自动化运维工具&#xff0c;可以自动化IT基础设施的配置和管理。Puppet使用声明性语言来描述系统状态&#xff0c;并通过客户端-服务器模型来实现自动化。Puppet manifes…

[C++]——同步异步日志系统(5)

同步异步日志系统 一、日志消息格式化设计1.1 格式化子项类的定义和实现1.2 格式化类的定义和实现 二、日志落地类设计2.1 日志落地模块功能实现与测试2.2 日志落地模块功能功能扩展 一、日志消息格式化设计 日志格式化模块的作用&#xff1a;对日志消息进行格式化&#xff0c…

深度学习工具和资源推荐:全面指南

今天我们来聊聊深度学习的工具和资源。要学好深度学习&#xff0c;除了理论知识&#xff0c;还需要掌握一些强大的工具和找到好的资源。以下是我在学习过程中发现的一些非常有用的工具和资源&#xff0c;希望对你们有帮助。 目录 工具推荐 1. Python编程语言 2. TensorFlow…

接口测试返回参数的自动化对比!

引言 在现代软件开发过程中&#xff0c;接口测试是验证系统功能正确性和稳定性的核心环节。接口返回参数的对比不仅是确保接口功能实现的手段&#xff0c;也是测试过程中常见且重要的任务。为了提高对比的效率和准确性&#xff0c;我们可以通过自动化手段实现这一过程。本文将…

WGCLOUD登录页面支持输入验证码吗

支持的 v3.5.3版本开始&#xff0c;WGCLOUD支持在登录页面配置输入验证码&#xff0c;我们可以根据自己的场景需要&#xff0c;配置是否在登录页面显示验证码&#xff0c;如下说明 登录页面添加验证码说明 - WGCLOUD

[超级详细系列]ubuntu22.04配置深度学习环境(显卡驱动+CUDA+cuDNN+Pytorch)--[3]安装cuDNN与Pytorch

本次配置过程的三篇博文分享分别为为&#xff1a; [超级详细系列]ubuntu22.04配置深度学习环境(显卡驱动CUDAcuDNNPytorch)--[1]安装显卡驱动 [超级详细系列]ubuntu22.04配置深度学习环境(显卡驱动CUDAcuDNNPytorch)--[2]安装Anaconda与CUDA [超级详细系列]ubuntu22.04配置深…

代码随想录 day38 动态规划part04

416. 分割等和子集 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200示例 1:输入: [1, 5, 11, 5] 输出: true 解释: 数组可以分割成 [1, 5, 5] 和 [11]. …

Web学习day04

mybatis 目录 mybatis 文章目录 一、查询 1.1结果映射 1.2多条件查询 1.3模糊查询 二、XML 书写规范 三、动态SQL 四、配置文件 4.1settings标签 4.2mappers标签 4.3environments标签 五、案例 5.1数据表 5.2实现类 5.3mapper实现 5.4工具类实现 5.5XML动态…

解决spring boot中使用拦截器导致swagger文档无法访问

目录 问题场景 解决方案 问题场景 我们的spring boot项目通常会使用接口文档管理依赖如knife4j(swagger3) Spring Boot3整合knife4j(swagger3)_springboot3 knife4j-CSDN博客 通常也会使用拦截器来做登录鉴权、接口限流等操作&#xff0c;但是使用拦截器会导致swagger接口…

FFmpeg学习(五)-- libswresample使用说明及函数介绍

libswresample Audio合成和重采样 libswresample库用来进行audio数据的合成和重采样操作。调用流程&#xff1a; 调用 swr_alloc 创建SwrContext结构体。设置SwrContext参数&#xff0c;有两种方法&#xff1a; 调用av_opt_set_xx函数逐项设置参数&#xff1b;swr_alloc_set_…

Python应用 | 基于flask-restful+AntDesignVue实现的一套图书管理系统

本文将分享个人自主开发的一套图书管理系统&#xff0c;后端基于Python语言&#xff0c;采用flask-restful开发后端接口&#xff0c;前端采用VueAntDesignVue实现。对其他类似系统的实现&#xff0c;比如学生管理系统等也有一定的参考作用。有问题欢迎留言讨论~ 关注公众号&am…

04.为什么line-height是无单位的 兄弟元素淡出效果 蚀刻文字效果

为什么 CSS 中的 line-height 应该是无单位的? 我经常听说 line-height 应该始终是无单位的。在我早期的编码年代,我没有过多地质疑这一点,但最近我开始想知道为什么会这样。在我看来,1.5 和 1.5em 应该产生相同的结果,对吧?事实证明,它们并非如此。 两者之间有一个细微的区…

记一下blender曲线阵列

先说一下如何正常使用这个 这一次我是用来贴瓷砖 随便创建一个mesh 然后添加一个阵列修改器&#xff0c;然后再给他添加一个curve修改器&#xff0c;使用constant offset去偏移他 这里有个小细节 我第一次创建的curve 我选取之后&#xff0c;死活无法沿着曲线阵列&#xff…

Dockerfile指令

Dockerfile指令 1、Dockerfile指令? 1)、COPY&#xff1a;类似ADD&#xff0c;将我们的文件拷贝到镜像中&#xff0c;也就是复制本地(宿主机)上的文件到镜像。 COPY [--chown<user>:<group>] ["<源路径1>",... "<目标路径>"] …

.快速幂.

按位与&#xff08;Bitwise AND&#xff09;是一种二进制运算&#xff0c;它逐位对两个数的二进制表示进行运算。对于每一位&#xff0c;只有两个相应的位都为1时&#xff0c;结果位才为1&#xff1b;否则&#xff0c;结果位为0。如&#xff1a;十进制9 & 5转化为二进制&am…