【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;高…

寒假提升(6)[杂烩典型题]

天可补&#xff0c;海可填&#xff0c;南山可移。 日月既往&#xff0c;不可复追。 ——曾国藩 知识点 1、关于整形提升2、大小端3、使用函数时参数的影响3、1、计算大小(有函数存在)3、2、计算大小(无函数存在)3、3、形参和实参 4、关于赋值 1、关于整形提升 char a101; int …

算法竞赛例题讲解:平方差 第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组 C平方差

题目描述 给定 L L L和 R R R&#xff0c;问 L ≤ x ≤ R L\leq x \leq R L≤x≤R中有多少个数 x x x满足存在整数 y y y, z z z使得 x y 2 − z 2 x y^{2} - z^{2} xy2−z2。 输入格式 输入一行包含两个整数 L L L, R R R&#xff0c;用一个空格分隔。 输出格式 输出一…

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

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

刷题13 数组

989. 数组形式的整数加法 整数的 数组形式 num 是按照从左到右的顺序表示其数字的数组。例如&#xff0c;对于 num 1321 &#xff0c;数组形式是 [1,3,2,1] 。 给定 num &#xff0c;整数的 数组形式 &#xff0c;和整数 k &#xff0c;返回 整数 num k 的 数组形式 。 输入…

12118 - Inspector‘s Dilemma (UVA)

题目链接如下&#xff1a; Online Judge 脑雾严重&#xff0c;这道题一开始我想的方向有问题.....后来看了别人的题解才写出来的..... 用的是欧拉路径的充要条件&#xff1b;以及数连通块。需要加的高速路数目 连通块个数 - 1 sum&#xff08;每个连通块中连成欧拉路径需要…

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

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

Hibernate JPA-@PreUpdate 和@PrePersist、@MappedSuperclass应用场景

文章目录 PrePersist注解 和 PreUpdate注解PreUpdatePrePersist 应用场景给一张表加上create_time&#xff0c;update_time这样的字段&#xff0c;想实现自动保存&#xff0c;更新这两个字段 MappedSuperclassInheritanceSINGLE_TABLE(将所有父类和子类集合在一张表)TABLE_PER_…

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

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

【Make编译控制 07】CMake常用命令

目录 一、变量相关命令 1. 定义变量 2. 设置C标准 3. 设置输出路径 二、文件相关命令 1. file 命令 2. aux_source_directory 命令 2. include_directories 命令 三、字符串相关命令 1. 字符串输出 2. 字符串拼接 3. 字符串移除 前情提示&#xff1a;【Make编译控制 …

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

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

Python装饰器详解:实例分析与使用场景

在Python中,装饰器是一种强大的语法特性,允许在不修改原始代码的情况下,动态地修改或增强函数的行为。本文将通过两个实际的例子,分别介绍了计时装饰器和缓存装饰器,并深入探讨了它们的实现原理和使用场景。 1. 计时装饰器 import timedef timing_decorator(func):def w…

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

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

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

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

KMP算法与前缀函数

KMP算法与前缀函数 说明 本文参考了 OI Wiki。 首先来明确几个概念&#xff1a; 后缀&#xff1a;后缀是从父串某个位置i开始到末尾结束的一个特殊字符串。真后缀&#xff1a;不为父串本身的后缀字符串。前缀&#xff1a;从父串开头到某个位置i结束的一个特殊字符串。真前缀…

in r, 找出所有重复的元素,包括第一个 R语言|如何筛选所有的重复行(包括第一行重复在内)

library(dplyr) data <- metadata %>%group_by(type) %>% # 根据你要筛选的列进行分组filter(duplicated(type)|n()!1) %>% # 将该列中有重复的行挑选出来ungroup() 方法二 # 示例向量 x <- c(1, 2, 3, 2, 4, 5, 5, 6)# 找出所有重复的元素&#xff08;包括第一…

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

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

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

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

Python爬虫:搭建本地IP池

本地代理IP池 代理IP池是一种由多个代理IP构成的集合&#xff0c;可以通过接口等方式随时获取可用的代理IP。通俗地打个比方&#xff0c;它就是一个池子&#xff0c;里面装了很多代理ip。代理IP具有以下几个特征&#xff1a; 1、池子里的ip是有生存周期的&#xff0c;它们将被…

Nginx配置php留档

好久没有用过php了&#xff0c;近几日配置nginxphp&#xff0c;留档。 安装 ubunt下nginx和php都可以使用apt安装&#xff1a; sudo apt install nginx php8 如果想安装最新的php8.2,则需要运行下面语句&#xff1a; sudo dpkg -l | grep php | tee packages.txt sudo add-…