顺序表专题

文章目录

  • 目录
    • 1. 数据结构相关概念
      • 1.1 什么是数据结构
      • 1.2 为什么需要数据结构
    • 2. 顺序表的概念及结构
    • 3. 顺序表分类
    • 4. 实现动态顺序表
      • 4.1 初始化
      • 4.2 顺序表的尾部插入
      • 4.3 打印顺序表
      • 4.4 顺序表的头部插入
      • 4.5 顺序表的尾部删除
      • 4.6 顺序表的头部删除
      • 4.7 指定位置之前插入数据
      • 4.8 删除指定位置数据
      • 4.9 在顺序表中查找x
      • 4.10 顺序表的销毁

目录

  • 数据结构相关概念
  • 顺序表概念及结构
  • 顺序表分类
  • 实现动态顺序表

1. 数据结构相关概念

1.1 什么是数据结构

数据结构是由“数据”和“结构”两词组合而来。

什么是数据?

常见的数值1、2、3、4…、教务系统里保存的用户信息(姓名、性别、年龄、学历等等)、网页里肉眼可以看到的信息(文字、图片、视频等等),这些都是数据。

什么是结构?

当我们想要大量使用同⼀类型的数据时,通过手动定义大量的独立的变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将⼤量的数据组织在⼀起,结构也可以理解为组织数据的方式。

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

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

1.2 为什么需要数据结构

程序中如果不对数据进行管理,可能会导致数据丢失、操作数据困难、野指针等情况。通过数据结构,能够有效将数据组织和管理在⼀起。按照我们的方式任意对数据进行增删改查等操作。

最基础的数据结构:数组。

【思考】有了数组,为什么还要学习其他的数据结构?

假定数组有10个空间,已经使用了5个,向数组中插入数据的步骤:

  1. 求数组的长度,求数组的有效数据个数
  2. 向下标为数据有效个数的位置插入数据(注意:这里是否要判断数组是否满了,满了还能继续插入吗)
  3. 假设数据量非常庞大,频繁的获取数组有效数据个数会影响程序执行效率。

结论: 最基础的数据结构能够提供的操作已经不能完全满足复杂算法实现。

2. 顺序表的概念及结构

线性表:

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

顺序表:

逻辑结构是线性的、物理结构是连续的。

顺序表和数组的区别:

顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。

3. 顺序表分类

  1. 静态顺序表

概念:使用定长数组存储元素

//静态顺序表#define N 100typedef int SLDataType;//顺序表中数组类型不一定是整型,如果要变为字符类型,就可以在这里直接改;如果不这样定义,就要在代码中改很多次struct SeqList
{SLDataType a[N];//定长数组int size;//有效数据个数
};

静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费

  1. 动态顺序表
//动态顺序表typedef int SLDataType;typedef struct SeqList
{SLDataType* arr;//存储数据的底层结构int capacity;//记录顺序表的空间大小int size;//记录顺序表当前有效的数据个数
}SL;//typedef struct SeqList SL;

4. 实现动态顺序表

4.1 初始化

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

4.2 顺序表的尾部插入

void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = 0 == ps->capacity ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (NULL == tmp){perror("realloc fail!");exit(1);}//扩容成功ps->arr = tmp;ps->capacity = newCapacity;}
}void SLPushBack(SL* ps, SLDataType x)
{//断言 -- 粗暴的解决方式//assert(ps != NULL);assert(ps);//if判断 -- 温柔的解决方式//if (NULL == ps)//{//	return;//}//空间不够,扩容SLCheckCapacity(ps);//空间足够,直接插入ps->arr[ps->size++] = x;//ps->size++;
}

注:
扩容的原则:成倍数的增加(1.5倍、2倍)

4.3 打印顺序表

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

4.4 顺序表的头部插入

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++;
}

4.5 顺序表的尾部删除

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

4.6 顺序表的头部删除

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--;
}

4.7 指定位置之前插入数据

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

4.8 删除指定位置数据

void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//pos以后的数据往前挪动一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

4.9 在顺序表中查找x

int SLFind(SL* ps, SLDataType x)
{//加上断言对代码的健壮性更好assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->arr[i]){return i;}}return -1;
}

4.10 顺序表的销毁

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

完整代码:

//SeqList.h#include <stdio.h>
#include <stdlib.h>
#include <assert.h>静态顺序表
//
//#define N 100
//
//typedef int SLDataType;
//
//struct SeqList
//{
//	SLDataType a[N];
//	int size;
//};//动态顺序表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, int pos, SLDataType x);
void SLErase(SL* ps, int pos);int SLFind(SL* ps, SLDataType x);
//SeqList.c#include "SeqList.h"//初始化和销毁
void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newCapacity = 0 == ps->capacity ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));if (NULL == tmp){perror("realloc fail!");exit(1);}//扩容成功ps->arr = tmp;ps->capacity = newCapacity;}
}//顺序表的头部/尾部插入
void SLPushBack(SL* ps, SLDataType x)
{//断言 -- 粗暴的解决方式//assert(ps != NULL);assert(ps);//if判断 -- 温柔的解决方式//if (NULL == ps)//{//	return;//}//空间不够,扩容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->size);SLCheckCapacity(ps);//pos及之后的数据往后挪动一位,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(pos >= 0 && pos < ps->size);//pos以后的数据往前挪动一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//在顺序表中查找x
int SLFind(SL* ps, SLDataType x)
{//加上断言对代码的健壮性更好assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->arr[i]){return i;}}return -1;
}void SLDestroy(SL* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
//test.c#include "SeqList.h"void slTest01()
{SL sl;SLInit(&sl);//测试尾插SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPrint(&sl);//SLPushBack(&sl, 5);//SLPrint(&sl);//SLPushBack(NULL, 6);//头插//SLPushFront(&sl, 5);//SLPushFront(&sl, 6);//SLPushFront(&sl, 7);//SLPrint(&sl);//尾删//SLPopBack(&sl);//SLPopBack(&sl);//SLPopBack(&sl);//SLPopBack(&sl);//SLPrint(&sl);//头删//SLPopFront(&sl);//SLPopFront(&sl);//SLPopFront(&sl);//SLPopFront(&sl);//SLPrint(&sl);//指定位置插入//SLInsert(&sl, 0, 100);//SLPrint(&sl);//SLInsert(&sl, sl.size, 200);//SLPrint(&sl);//SLInsert(&sl, 100, 300);//SLPrint(&sl);//删除指定位置的数据//SLErase(&sl, 0);//SLPrint(&sl);//SLErase(&sl, sl.size - 1);//SLPrint(&sl);SLErase(&sl, 1);SLPrint(&sl);
}void slTest02()
{SL sl;SLInit(&sl);//测试尾插SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLPrint(&sl);//测试查找//int ret = SLFind(&sl, 3);int ret = SLFind(&sl, 30);if (ret < 0){printf("数据不存在,查找失败!");}else{printf("数据找到了,在下标为%d位置\n", ret);}
}int main()
{//slTest01();slTest02();return 0;
}

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

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

相关文章

词-词共现概率与Transformer

1.词词共现概率 词-词共现概率是自然语言处理中的一个关键概念&#xff0c;它描述的是在一段文本或一个大型语料库中&#xff0c;任意两个词在同一上下文中共同出现的概率。具体来说&#xff0c;如果我们在分析语料库时发现词A和词B经常相邻出现或者在一定距离范围内出现&#…

ajax, axios, 同步和异步

Ajax和同步与异步 今日目标&#xff1a; 1.利用原生ajax发送get和post请求 2.利用axios发送get和post请求 3.同步和异步 01-Ajax概述【了解】 概念&#xff1a; async javascript and xml: 异步的js和xml优点&#xff1a; 无刷新提交数据&#xff0c;用户体验好缺点&…

kafka学习笔记02(小滴课堂)

Kafka命令行生产者发送消息和消费者消费消息实战 已存在的kafka不能重复创建。 broker设置的是1&#xff0c;factor大于broker了&#xff0c;所以报错。 生产者发送消息&#xff1a; kafka列表出现了新的kafka。 我们使用这个kafka。 我们启动消费者&#xff1a; 我们现在不从…

PYTHON调离线语音合成并实时播放

1、资源下载&#xff08;可以去讯飞官网控制台下载&#xff09; 2、实现代码 # Python调普通离线合成并实时播放 import wave from ctypes import * import pyaudio""" 1、 在Python中某些时候需要C做效率上的补充&#xff0c;Python中的ctypes模块可以很方便…

csv文件转换成list 代码

hb [] h open("your_file.csv","r",encoding "utf-8") data h.read() #print(type(data)) rows data.split("\n") # 数据切分&#xff0c;以换行&#xff08;“\n”&#xff09;为基准&#xff0c;形成一个list&#xff0c;每一行…

【Qt 学习笔记】Day1 | Qt 背景介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Day1 | Qt 背景介绍 文章编号&#xff1a;Qt 学习笔记 / 01 文章目录…

C/C++语言实现简易通讯录 [含文件操作,循环双链表]

文章目录 C/C语言实现简易通讯录概要基本功能运行截图展示主要代码展示 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alaskan Malamute &#x1f4dc; 博主的代码仓库主页 [ Gitee ]&#xff1a;ryanala [GitHub]&#xff1a; Ryan-Ala C/C语言实现简易通讯录 ⚠⚠⚠ …

话题通信的python实现

一、发布者Publisher的python实现 step1&#xff1a;在scripts文件夹中创建py节点 step2&#xff1a;第一行是为了指定解释器&#xff0c;Ubuntu20.04是python3&#xff0c;比他低的版本是python。第二行是为了指定编码方式。第五行中&#xff0c;引用index.ros.org中数据类型…

RVM安装ruby笔记

环境 硬件&#xff1a;Macbook Pro 系统&#xff1a;macOS 14.1 安装公钥 通过gpg安装公钥失败&#xff0c;报错如下&#xff1a; 换了几个公钥地址&#xff08;hkp://subkeys.pgp.net&#xff0c;hkp://keys.gnupg.net&#xff0c;hkp://pgp.mit.edu&#xff09;&#xff0c;…

论文笔记:Retrieval-Augmented Generation forAI-Generated Content: A Survey

北大202402的RAG综述 1 intro 1.1 AICG 近年来&#xff0c;人们对人工智能生成内容&#xff08;AIGC&#xff09;的兴趣激增。各种内容生成工具已经精心设计&#xff0c;用于生产各种模态下的多样化对象 文本&代码&#xff1a;大型语言模型&#xff08;LLM&#xff09;…

MySQL分表后,如何做分页查询?

参考: https://blog.csdn.net/qq_44732146/article/details/127616258 user.sql 完整的执行一遍&#xff0c;可以做到分表和分页 数据是实时的&#xff0c;往一张子表里插入之后&#xff0c;all表就能立刻查询到 在这里实现分页查询的是MyIsam引擎&#xff0c;这个引擎不支持…

Java:链表

一、链表简介 1、链表与顺序表的区别 上一篇博客我介绍了顺序表&#xff0c;这次我们来认识认识链表&#xff01;先来看看二者的区别&#xff1a; 顺序表&#xff1a;由于顺序表实际上是一个数组&#xff0c;因此它在物理上是连续的&#xff0c;逻辑上也是连续的&#xff01; …

HJ5 进制转换

目录 问题描述 输入描述&#xff1a; 输出描述&#xff1a; 示例 解释 思路 代码实现 问题描述 写出一个程序&#xff0c;接受一个十六进制的数&#xff0c;输出该数值的十进制表示。 输入描述&#xff1a; 输入一个十六进制的数值字符串 输出描述&#xff1a; 输出该数…

【IDEA】使用debug方式去运行java程序

什么是debug工具&#xff1f; 调试工具&#xff08;debug工具&#xff09;是一种用于帮助程序员识别和修复程序中的错误的工具。它们提供了一系列的功能&#xff0c;帮助程序员在代码执行的过程中跟踪和检测问题&#xff0c;例如查看变量的值、检查函数的调用栈、设置断点来停…

Spring学习——什么是循环依赖及其解决方式

文章目录 前言一、什么是循环依赖二、解决思路1、循环依赖分类2、对象初始化步骤及对象分类3、spring是如何解决的4、图解5、三级缓存1、区别2、ObjectFactory是什么 三、源码debug1、spring创建对象过程1、dubug第一步——找到getBean2、dubug第二步——getBean与doGetBean3、…

腾讯 tendis 替代 redis linux安装使用

下载地址 Tendis存储版 点击下载 linux 解压 tar -zxvf 安装包.tgz cd 解压安装包/scripts 启动 ./start.sh 停止 ./stop.sh 详细配置 修改 /scripts tendisplus.conf # tendisplus configuration for testing # 绑定本机IIP bind 192.168.31.112 port 51002 #设…

MySQL的安装配置 及 MySQL配置,服务管理,基本使用,性能优化,安全性,监控与日志管理,扩展与高可用,备份与恢复,版本升级与迁移注意事项

MySQL的安装配置可以分为几个主要步骤&#xff0c;包括安装MySQL、验证安装是否成功、配置环境变量以及进行MySQL的配置。以下是详细的教程&#xff1a; 一、安装MySQL 首先&#xff0c;从MySQL官网下载MySQL安装包。进入官网后&#xff0c;找到“DOWNLOADS”部分&#xff0c…

海格里斯助推实体制造业转型升级 “算法定义硬件”解题AIoT市场

随着自动化的发展&#xff0c;电子商务和智能制造推动了自动化立体仓库的快速发展与创新&#xff0c;产生了“密集仓储”的概念。对于一个实体企业来讲&#xff0c;其数智物流转型正在趋向于“去伪存真”&#xff0c;企业追求高ROI与真实经济价值&#xff0c;具有降本增效的业务…

代码随想录算法训练营第三十三天|leetcode70、509、746题

一、leetcode第509题 本题要求斐波那契数列的通式&#xff0c;通过定义dp数组&#xff0c;确定dp[i]dp[i-1]dp[i-2]的递推式&#xff0c;从而确定dp数组的含义为第i个数的大小。 具体代码如下&#xff1a; class Solution { public:int fib(int n) {if(n0){return 0;}if(n1)…

JavaEE 初阶篇-深入了解多线程安全问题(出现线程不安全的原因与解决线程不安全的方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 多线程安全问题概述 1.1 线程不安全的实际例子 2.0 出现线程不安全的原因 2.1 线程在系统中是随机调度且抢占式执行的模式 2.2 多个线程同时修改同一个变量 2.3 线…