【C语言|数据结构】数据结构顺序表

目录

一、数据结构

1.1概念

1.2总结

1.3为什么需要数据结构?

二、顺序表

1.顺序表的概念及结构

1.1线性表

2.顺序表分类

2.1顺序表和数组的区别

2.2顺序表的分类

2.2.1静态顺序表

2.2.1.1概念

2.2.1.2缺陷

2.2.2动态顺序表

三、动态顺序表的实现

3.1新建项目

3.2 SeqList.h

3.3SeqList.c

3.3.1初始化

3.3.2销毁

3.3.3打印

3.3.4扩容

3.3.4.1扩容原则选择

3.3.4.2扩容代码呈现

3.3.5尾插

3.3.6头插

3.3.7尾删

3.3.8头删

3.3.9指定位置之前插入数据

3.3.10指定位置之前删除数据

3.3.11查找

3.3.12 SeqList.c


一、数据结构

1.1概念

  • 数据结构是计算机存储、组织数据的⽅式。
  • 数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么⽅式构成,以及数据元素之间呈现的结构。

1.2总结

  • 1)能够存储数据(如顺序表、链表等结构)
  • 2)存储的数据能够⽅便查找

1.3为什么需要数据结构?

  • 程序中如果不对数据进⾏管理,可能会导致数据丢失、操作数据困难、野指针等情况。 通过数据结构,能够有效将数据组织和管理在⼀起。按照我们的⽅式任意对数据进⾏增删改查等操作。
  • 最基础的数据结构:数组。
  • 【思考】有了数组,为什么还要学习其他的数据结构?
  • 假定数组有10个空间,已经使⽤了5个,向数组中插⼊数据步骤: 求数组的⻓度,求数组的有效数据个数,向下标为数据有效个数的位置插⼊数据(注意:这⾥是 否要判断数组是否满了,满了还能继续插⼊吗)..... 假设数据量⾮常庞⼤,频繁的获取数组有效数据个数会影响程序执⾏效率。
  • 结论:最基础的数据结构能够提供的操作已经不能完全满⾜复杂算法实现。

二、顺序表

1.顺序表的概念及结构

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

2.顺序表分类

2.1顺序表和数组的区别
  • 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝
2.2顺序表的分类
2.2.1静态顺序表
2.2.1.1概念
  • 使⽤定⻓数组存储元素
2.2.1.2缺陷
  • 空间给少了不够⽤,给多了造成空间浪费

2.2.2动态顺序表

三、动态顺序表的实现

3.1新建项目

3.2 SeqList.h

//C语言
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLDataType;//不仅限于int类型 便于后续替换//动态顺序表
typedef struct SeqList
{SLDataType* arr;   //存储数据的底层结构int capacity;      //记录顺序表的空间大小int size;          //记录顺便当前有效的数据个数}SL;//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);//尾插/尾删/头插/头删
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

3.3SeqList.c

3.3.1初始化

void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = 0;ps->size = 0;}

3.3.2销毁


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

3.3.3打印

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

3.3.4扩容

3.3.4.1扩容原则选择
  • 一次扩充一个空间:插入一个元素还不会造成空间浪费 ✖ 程序执行效率低下
  • 一次扩充固定个大小的空间(10、100)✖ 小了:造成频繁扩容,会造成程序运行低下;大了:造成空间浪费
  • 成倍数的扩增(1.5倍、2倍)✅相对高效:数据插入的越多,扩容的大小越来越大即插入数据的数量与扩容大小成近似真相关
3.3.4.2扩容代码呈现
  1. 首先判断动态数组的元素个数(size)是否等于容量(capacity)。
  2. 若相等,则需要进行扩容操作。
  3. 计算新的容量大小,如果原容量为0,则新容量为4,否则新容量为原容量的两倍。
  4. 调用realloc函数重新分配内存空间,将原动态数组的元素拷贝到新的内存空间中。
  5. 如果内存分配失败(temp为NULL),则输出错误信息并退出程序。
  6. 如果内存分配成功,则将新的内存空间地址赋值给动态数组指针arr,同时更新容量为新的容量大小。
//扩容
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* temp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (temp == NULL){perror("realloc fail!");//扩容失败exit(1);//退出}//扩容成功ps->arr = temp;ps->capacity = newCapacity;}}

3.3.5尾插

//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//断言,确保不为空//空间不够直接插入SLCheckCapacity(ps);//空间足够直接插入ps->arr[ps->size] = x;ps->size++;
}

3.3.6头插


//头插
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];}ps->arr[0] = x;ps->size++;}

3.3.7尾删

//尾删
void SLPopBack(SL* ps)
{//顺序表为空assert(ps);assert(ps->size);//顺序表不为空ps->size--;
}

3.3.8头删

//头删
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--;
}

3.3.9指定位置之前插入数据

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->arr);SLCheckCapacity(ps);//pos及之后的数据挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;}

3.3.10指定位置之前删除数据

void SLErase(SL* ps, int pos)
{assert(ps);assert(ps >= 0 && pos < ps->size);for (int i = pos;i < ps->size;i++){ps->arr[i] = ps->arr[i + 1];}
}

3.3.11查找

int SLFind(SL* ps, SLDataType x)
{for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1; // 表示未找到
}

3.3.12 SeqList.c

#include"SeqList.h"//初始化和销毁
void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = 0;ps->size = 0;}void SLDestroy(SL* ps)
{free(ps->arr);ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}//打印
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}//扩容
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* temp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (temp == NULL){perror("realloc fail!");//扩容失败exit(1);//退出}//扩容成功ps->arr = temp;ps->capacity = newCapacity;}}//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//断言,确保不为空//空间不够直接插入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];}ps->arr[0] = 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 SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->arr);SLCheckCapacity(ps);//pos及之后的数据挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;}void SLErase(SL* ps, int pos)
{assert(ps);assert(ps >= 0 && pos < ps->size);for (int i = pos;i < ps->size;i++){ps->arr[i] = ps->arr[i + 1];}
}int SLFind(SL* ps, SLDataType x)
{for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1; // 表示未找到
}

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

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

相关文章

如何部署一个高可用的 Linux 集群?

部署一个高可用的 Linux 集群需要经过多个步骤和考虑因素。以下是一个简要的指南&#xff0c;帮助您了解如何部署一个高可用的 Linux 集群&#xff1a; 确定需求和目标&#xff1a;在开始部署之前&#xff0c;您需要明确高可用性的定义和目标。对于一些组织而言&#xff0c;高…

计算机设计大赛 深度学习 机器视觉 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 车位识别车道线检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) …

EMC学习笔记(二十三)降低EMI的PCB设计指南(三)

双层板电源分配 1.单点与多点分布2.星型分布3.创建网格平面4.旁路和磁珠5.将噪声保持在芯片附近 tips&#xff1a;资料主要来自网络&#xff0c;仅供学习使用。 1.单点与多点分布 在一个真正的单点配电系统中&#xff0c;每个有源元件都有自己独立的电源和地&#xff0c;这些…

【React】如何使antd禁用状态的表单输入组件响应点击事件?

最近遇到一个需求&#xff0c;需要在<Input.textarea>组件中&#xff0c;设置属性disabled为true&#xff0c;使textarea响应点击事件&#xff0c;但直接绑定onClick并不会在禁用状态下被响应。 解决方法1 之后尝试了很多方法&#xff0c;比如设置csspointer-events:no…

【Dubbo源码二:Dubbo服务导出】

入口 Dubbo服务导出的入口&#xff1a;服务导出是在DubboBootstrapApplicationListener在监听到ApplicationContextEvent的ContextRefreshedEvent事件后&#xff0c;会触发dubboBootstrap.start(), 在这个方法中最后会导出Dubbo服务 DubboBootstrapApplicationListener Dub…

无人机飞控算法原理基础研究,多旋翼无人机的飞行控制算法理论详解,无人机飞控软件架构设计

多旋翼无人机的飞行控制算法主要涉及到自动控制器、捷联式惯性导航系统、卡尔曼滤波算法和飞行控制PID算法等部分。 自动控制器是无人机飞行控制的核心部分&#xff0c;它负责接收来自无人机传感器和其他系统的信息&#xff0c;并根据预设的算法和逻辑&#xff0c;对无人机的姿…

【基础】比较器 - 振荡来自何处?

比较器是一个简单的概念-在输入端对两个电压进行比较。输出为高或者低。因此&#xff0c;在转换的过程中为什么存在振荡。 当转换电平缓慢改变的时候&#xff0c;这个现象经常会发生。常常是由于输入信号存在噪声&#xff0c;因此在转换电平附近的轻微波动会引起输出端的振荡。…

基于深度学习算法的轴承故障自主分类

1. 要求 轴承有3种故障&#xff1a;外圈故障&#xff0c;内圈故障&#xff0c;滚珠故障&#xff0c;外加正常的工作状态。如表1所示&#xff0c;结合轴承的3种直径&#xff08;直径1,直径2,直径3&#xff09;&#xff0c;轴承的工作状态有10类&#xff1a; 表1 轴承故障类别 外…

单片机学习路线(简单介绍)

学习单片机对于电子爱好者和未来的嵌入式系统工程师来说是一段激动人心的旅程。单片机因其强大的功能、灵活性以及在各种智能设备中的广泛应用&#xff0c;成为了电子和计算机科学领域一个不可或缺的组成部分。如果你对如何开始这段旅程感到好奇&#xff0c;那么你来对地方了。…

计算机算术

计算机算术 数据是什么 数据是各种各样的信息&#xff0c;如数字、文本、计算机程序、音乐、图像、符号等等&#xff0c;实际上&#xff0c;信息可以是能够被计算机存储和处理的任何事物。 位与字节 计算机中存储和处理信息的最小单位是位&#xff08;Binary digit比特&#x…

[动态规划]判断整除

题目 一个给定的正整数序列&#xff0c;在每个数之前都插入号或-号后计算它们的和。比如序列&#xff1a;1、2、4共有8种可能的序列&#xff1a; (1) (2) (4) 7 (1) (2) (-4) -1 (1) (-2) (4) 3 (1) (-2) (-4) -5 (-1) (2) (4) 5 (-1) (2) (-4) -3 (…

Open CASCADE学习|保存为STL文件

STL (Stereolithography) 文件是一种广泛用于3D打印和计算机辅助设计 (CAD) 领域的文件格式。它描述了一个三维模型的表面而不包含颜色、材质或其他非几何信息。STL文件通常用于3D打印过程中&#xff0c;因为它们仅包含构建物体所需的位置信息。 由于STL文件只包含表面信息&am…

【开源项目阅读】Java爬虫抓取豆瓣图书信息

原项目链接 Java爬虫抓取豆瓣图书信息 本地运行 运行过程 另建项目&#xff0c;把四个源代码文件拷贝到自己的包下面 在代码爆红处按ALTENTER自动导入maven依赖 直接运行Main.main方法&#xff0c;启动项目 运行结果 在本地磁盘上生成三个xml文件 其中的内容即位爬取…

论文阅读-CARD:一种针对复制元数据服务器集群的拥塞感知请求调度方案

论文名称&#xff1a;CARD: A Congestion-Aware Request Dispatching Scheme for Replicated Metadata Server Cluster 摘要 复制元数据服务器集群&#xff08;RMSC&#xff09;在分布式文件系统中非常高效&#xff0c;同时面对数据驱动的场景&#xff08;例如&#xff0c;大…

ECMAScript Modules规范的示例详解

ECMAScript Modules&#xff08;ESM&#xff09;是JavaScript中用于模块化开发的规范&#xff0c;它允许开发者将代码分割成多个独立的文件&#xff0c;以提高代码的可维护性和可重用性。下面是一个ECMAScript Modules规范的示例详解&#xff1a; 创建模块 1.1 导出变量 在一个…

大数据Flume--入门

文章目录 FlumeFlume 定义Flume 基础架构AgentSourceSinkChannelEvent Flume 安装部署安装地址安装部署 Flume 入门案例监控端口数据官方案例实时监控单个追加文件实时监控目录下多个新文件实时监控目录下的多个追加文件 Flume Flume 定义 Flume 是 Cloudera 提供的一个高可用…

Python算法100例-1.4 百钱百鸡

1.问题描述2.问题分析3.算法设计4.知识点补充5.确定程序框架6.确定公鸡、母鸡和小鸡数量7.完整的程序8.问题拓展 完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1.问题描述 中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱百鸡问题”&#xf…

动态规划的一个初步学习

啥叫动态规划 在我们写很多的题目时&#xff0c;常常可以用暴力枚举来写&#xff0c;缺点就是速度太慢了。如果我们用一个数组或者哈希表&#xff08;虽然我还没学过哈希表&#xff09;将之前暴力枚举的数据储存起来&#xff0c;当再一次枚举到这个数字的时候就直接调用数组或…

Android---Jetpack Compose学习002

Compose 布局。Compose 布局的目标&#xff1a;1&#xff09;实现高性能&#xff1b;2&#xff09;让开发者能够轻松编写自定义布局&#xff1b;3&#xff09;在 Compose 中&#xff0c;通过避免多次测量布局子级可实现高性能。如果需要进行多次测量&#xff0c;Compose 具有一…

分享86个表单按钮JS特效,总有一款适合您

分享86个表单按钮JS特效&#xff0c;总有一款适合您 86个表单按钮JS特效下载链接&#xff1a;https://pan.baidu.com/s/1WwQGFPWv8464JBcuEMJZ_Q?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;…