顺序表的讲解与实现

顺序表的讲解与实现

  • 一、顺序表的概念及结构
  • 二、顺序表分类
    • 顺序表和数组的区别
    • 顺序表分类
      • 静态顺序表
      • 动态顺序表
  • 三、动态顺序表的实现(使用VS2022)
    • 1.初始化、销毁、打印内容
    • 2.检查扩容
    • 3.尾部插入、尾部删除、头部插入、头部删除
      • 尾部插入
      • 尾部删除
      • 头部插入
      • 头部删除
    • 4.指定插入、指定删除、查找
      • 指定插入
      • 指定删除
      • 查找
  • 四、代码优化
  • 五、完整 SeqList.c 代码

一、顺序表的概念及结构

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

二、顺序表分类

顺序表和数组的区别

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

顺序表分类

静态顺序表

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

#define N 10					// 长度恒定typedef int SeqListDataType;typedef struct SeqList
{SeqListDataType arr[N];		// 长度恒定int size;
} SeqList, *pSeqList;

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

动态顺序表

概念:按需申请,避免空间进一步浪费

typedef int SeqListDataType;typedef struct SeqList
{SeqListDataType* arr;		// 指针int size;					// 当前容量int capacity;				// 总容量
} SeqList, * pSeqList;

三、动态顺序表的实现(使用VS2022)

这里以实现动态顺序表为例,开发工具为VS2022

动态顺序表常用的增删改查等接口包括:

1.初始化、销毁、打印内容

2.检查扩容

3.尾部插入、尾部删除、头部插入、头部删除

4.指定插入、指定删除、查找

在 SeqList.h 中:

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>// 初始化容量
#define INIT_CAPACITY 4// 扩容倍率
#define EXPANSION_MULTIPLE 2typedef int SeqListDataType;typedef struct SeqList
{SeqListDataType* arr;int size;int capacity;
} SeqList, * pSeqList;// 初始化、销毁、打印
void SeqListInit(pSeqList ps);void SeqListDestroy(pSeqList ps);void SeqListPrint(pSeqList ps);// 检查扩容
void CheckCapacity(pSeqList ps);// 尾插尾删、头插头删
void SeqListPushBack(pSeqList ps, SeqListDataType x);void SeqListPopBack(pSeqList ps);void SeqListPushFront(pSeqList ps, SeqListDataType x);void SeqListPopFront(pSeqList ps);// 插入、删除、查找
void SeqListInsert(pSeqList ps, int pos, SeqListDataType x);void SeqListErase(pSeqList ps, int pos);int SeqListFind(pSeqList ps, SeqListDataType x);

在 SeqList.c 中:

1.初始化、销毁、打印内容

#include "SeqList.h"// 初始化、销毁、打印
void SeqListInit(pSeqList ps)
{assert(ps);			// 防止进入空指针ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}void SeqListDestroy(pSeqList ps)
{assert(ps);free(ps->arr);ps->size = 0;ps->capacity = 0;
}void SeqListPrint(pSeqList ps)
{assert(ps);for (int i = 0; i < ps->size; ++i){printf("%d ", ps->arr[i]);}printf("\n");
}

2.检查扩容

// 检查扩容
void CheckCapacity(pSeqList ps)
{assert(ps);if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : ps->capacity * EXPANSION_MULTIPLE;// ps->arr 为空时,realloc 会转为 mallocSeqListDataType* temp = (SeqListDataType*)realloc(ps->arr, newCapacity * sizeof(SeqListDataType));if (temp == NULL){perror("realloc failed");return;}// 更新ps->arr = temp;ps->capacity = newCapacity;}
}

3.尾部插入、尾部删除、头部插入、头部删除

尾部插入

void SeqListPushBack(pSeqList ps, SeqListDataType x)
{assert(ps);					CheckCapacity(ps);			// 检查容量,不足扩容ps->arr[ps->size++] = x;	// 尾插
}

尾部删除

void SeqListPopBack(pSeqList ps)
{assert(ps);assert(ps->size > 0);	// 防止为空--ps->size;				// 直接--忽略掉当前位置
}

头部插入

void SeqListPushFront(pSeqList ps, SeqListDataType x)
{assert(ps);CheckCapacity(ps);for (int end = ps->size; end > 0; --end){ps->arr[end] = ps->arr[end - 1];}ps->arr[0] = x;++ps->size;
}

在这里插入图片描述
在这里插入图片描述

头部删除

void SeqListPopFront(pSeqList ps)
{assert(ps);assert(ps->size > 0);for (int begin = 0; begin < ps->size - 1; ++begin){ps->arr[begin] = ps->arr[begin + 1];}--ps->size;
}

在这里插入图片描述
在这里插入图片描述

4.指定插入、指定删除、查找

指定插入

void SeqListInsert(pSeqList ps, int pos, SeqListDataType x)
{assert(ps);assert(0 <= pos && pos <= ps->size); // 当 pos == ps->size 可以实现尾插 CheckCapacity(ps);for (int end = ps->size; end > pos; --end){ps->arr[end] = ps->arr[end - 1];}ps->arr[pos] = x;++ps->size;
}

指定插入与头部插入同理,只需将结束位置改为 pos 指定的位置。

指定删除

void SeqListErase(pSeqList ps, int pos)
{assert(ps);assert(ps->size > 0);assert(0 <= pos && pos < ps->size);	// 尾删不可删 pos == ps->size 位置上的for (int begin = pos; begin < ps->size - 1; ++begin){ps->arr[begin] = ps->arr[begin + 1];}--ps->size;
}

指定删除与头部删除同理,只需将开始位置改为 pos 指定的位置。

查找

int SeqListFind(pSeqList ps, SeqListDataType x)
{assert(ps);assert(ps->size > 0);// 找到返回下标,反之返回 -1for (int i = 0; i < ps->size; ++i){if (ps->arr[i] == x){return i;}}return -1;
}

四、代码优化

指定插入 包含 尾插头插,指定删除 包含 尾删头删。可以复用两者,提高代码复用率

// 尾插尾删、头插头删
void SeqListPushBack(pSeqList ps, SeqListDataType x)
{SeqListInsert(ps, ps->size, x);
}void SeqListPopBack(pSeqList ps)
{SeqListErase(ps, ps->size - 1);
}void SeqListPushFront(pSeqList ps, SeqListDataType x)
{SeqListInsert(ps, 0, x);
}void SeqListPopFront(pSeqList ps)
{SeqListErase(ps, 0);
}

五、完整 SeqList.c 代码

#include "SeqList.h"// 初始化、销毁、打印
void SeqListInit(pSeqList ps)
{assert(ps);ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}void SeqListDestroy(pSeqList ps)
{assert(ps);free(ps->arr);ps->size = 0;ps->capacity = 0;
}void SeqListPrint(pSeqList ps)
{assert(ps);for (int i = 0; i < ps->size; ++i){printf("%d ", ps->arr[i]);}printf("\n");
}// 检查扩容
void CheckCapacity(pSeqList ps)
{assert(ps);if (ps->size == ps->capacity){int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : ps->capacity * EXPANSION_MULTIPLE;// ps->arr 为空时,realloc 会转为 mallocSeqListDataType* temp = (SeqListDataType*)realloc(ps->arr, newCapacity * sizeof(SeqListDataType));if (temp == NULL){perror("realloc failed");return;}// 更新ps->arr = temp;ps->capacity = newCapacity;}
}// 尾插尾删、头插头删
void SeqListPushBack(pSeqList ps, SeqListDataType x)
{SeqListInsert(ps, ps->size, x);
}void SeqListPopBack(pSeqList ps)
{SeqListErase(ps, ps->size - 1);
}void SeqListPushFront(pSeqList ps, SeqListDataType x)
{SeqListInsert(ps, 0, x);
}void SeqListPopFront(pSeqList ps)
{SeqListErase(ps, 0);
}// 插入、删除、查找
void SeqListInsert(pSeqList ps, int pos, SeqListDataType x)
{assert(ps);assert(0 <= pos && pos <= ps->size);CheckCapacity(ps);for (int end = ps->size; end > pos; --end){ps->arr[end] = ps->arr[end - 1];}ps->arr[pos] = x;++ps->size;
}void SeqListErase(pSeqList ps, int pos)
{assert(ps);assert(ps->size > 0);assert(0 <= pos && pos < ps->size);for (int begin = pos; begin < ps->size - 1; ++begin){ps->arr[begin] = ps->arr[begin + 1];}--ps->size;
}int SeqListFind(pSeqList ps, SeqListDataType x)
{assert(ps);assert(ps->size > 0);for (int i = 0; i < ps->size; ++i){if (ps->arr[i] == x){return i;}}return -1;
}

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

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

相关文章

C++ stack类与queue类

目录 0.前言 1.容器适配器 1.1容器适配器的特点 1.2容器适配器的实现 1.3使用容器适配器的场景 2.stack的介绍与使用 2.1介绍 2.2使用 3.queue的介绍与使用 3.1介绍 3.2使用 4.stack和queue的模拟实现 4.1 stack的模拟实现 4.2 queue的模拟实现 5.结语 &#xf…

博客星球大冒险:用Spring Boot和JWT打造你的数字王国

揭秘如何在Spring Boot中无缝集成JWT&#xff0c;为你的应用打造一个高度可扩展且安全的认证系统。从添加依赖到创建JWT过滤器&#xff0c;再到实现令牌的有效性管理和刷新机制&#xff0c;每一步都精心设计&#xff0c;确保你的乐园能够迎接成千上万的游客&#xff01; 文章目…

LLM主流开源代表模型

LLM主流开源大模型介绍 1 LLM主流大模型类别 随着ChatGPT迅速火爆&#xff0c;引发了大模型的时代变革&#xff0c;国内外各大公司也快速跟进生成式AI市场&#xff0c;近百款大模型发布及应用。 目前&#xff0c;市面上已经开源了各种类型的大语言模型&#xff0c;本章节我们…

【MATLAB源码-第220期】基于matlab的Massive-MIMO误码率随着接收天线变化仿真采用ZF均衡和QPSK调制。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 系统背景与目标 无线通信系统的发展极大地推动了现代通信技术的进步&#xff0c;从移动通信到无线局域网&#xff0c;甚至是物联网&#xff0c;均依赖于无线通信系统的高效和可靠性。在无线通信系统中&#xff0c;核心目…

【kafka】关于Kafka的入门介绍

为什么要使用kafka&#xff1f;kafka是什么东西&#xff1f; 案例场景 A服务向B服务发送消息&#xff0c;A服务传输数据很快&#xff0c;B服务处理数据很慢&#xff0c;这样B服务就会承受不住&#xff0c;怎么办&#xff1f;通过添加消息队列作为缓冲。kafka就是消息队列中的…

初识C++ · 模拟实现stack和Queue

目录 前言&#xff1a; 1 Stack 1.1 双端队列 2 Queue 前言&#xff1a; 经历了list三个自定义类型的洗礼&#xff0c;来个简单的放松放松&#xff0c;即栈和队列&#xff1a; 文档记录的&#xff0c;栈和队列是一种容器适配器&#xff0c;它们不属于stl&#xff0c;但是它…

低空经济发展报告

低空经济是指利用低空空间进行商业开发和经济活动的概念。随着航空技术的发展和无人机的普及&#xff0c;低空经济逐渐成为一个新兴的经济领域。 低空经济可以涵盖的领域非常广泛&#xff0c;包括但不限于物流配送、农业植保、城市交通、旅游观光等。利用无人机等飞行器进行物…

【算法】一文搞懂归并排序

概念 归并排序利用了分治思想&#xff0c;将待排序的数组范围层层划分&#xff0c;每次划分会得到两个大小相近的区间。当无法划分时&#xff0c;递归结束&#xff0c;自下而上进行区间合并merge操作&#xff0c;合并操作依次比较两个区间的元素&#xff0c;进而使合并后的区间…

【西瓜书】5.神经网络

1.概念 有监督学习正向传播&#xff1a;输入样本---输入层---各隐层---输出层反向传播&#xff1a;误差以某种形式在通过隐层向输入层逐层反转&#xff0c;并将误差分摊给各层的所有单元&#xff0c;以用于修正各层的权值激活函数&#xff1a;也叫阶跃函数&#xff0c;目的是引…

Maven 中的 classifier 属性用过没?

最近训练营有小伙伴问到松哥一个关于 Maven 依赖的问题&#xff0c;涉及到 classifier 属性&#xff0c;随机问了几个小伙伴&#xff0c;都说工作中没用到过&#xff0c;因此简单整篇文章和小伙伴们分享下。 Maven 大家日常开发应该都有使用&#xff0c;Maven 中有一个比较好玩…

最小二乘法算法(个人总结版)

最小二乘法&#xff08;Least Squares Method&#xff09;是一种通过最小化误差平方和来拟合数据的回归分析方法。它被广泛应用于线性回归、多元回归以及其他数据拟合问题中。以下是详细的教程&#xff0c;涵盖基本概念、数学推导、具体步骤和实现代码。 1. 最小二乘法基本概念…

装机必备——鲁大师安装教程

装机必备——鲁大师安装教程 软件下载 软件名称&#xff1a;鲁大师 软件语言&#xff1a;简体中文 软件大小&#xff1a;144.75M系统要求&#xff1a;Windows7或更高&#xff0c; 32/64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM2G或更高 下载通道①迅雷云盘丨…

p5开发helloworld

注意&#xff0c;执行的时候&#xff0c;后面不用带class的后缀

C语言(字符、字符串函数)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…

Pinia(三): 了解和使用state

1.state state 就是我们要定义的数据, 如果定义 store 时传入的第二个参数是对象, 那么 state 需要是一个函数, 这个函数的返回值才是状态的初始值.这样设计的原因是为了让 Pinia 在客户端和服务端都可以工作 官方推荐使用箭头函数(()>{ })获得更好的类型推断 import { de…

最新张量补全论文收集【8篇】

目录 1、利用张量子空间先验&#xff1a;增强张量补全的核范数最小化和 2、基于可学习空间光谱变换的张量核范数多维视觉数据恢复 3、用于图像补全的增强型低秩和稀疏 Tucker 分解 4、多模态核心张量分解及其在低秩张量补全中的应用 5、 低秩张量环的噪声张量补全 6、 视…

三十四、openlayers官网示例Dynamic clusters解析——动态的聚合图层

官网demo地址&#xff1a; https://openlayers.org/en/latest/examples/clusters-dynamic.html 这篇绘制了多个聚合图层。 先初始化地图 &#xff0c;设置了地图视角的边界extent&#xff0c;限制了地图缩放的范围 initMap() {const raster new TileLayer({source: new XYZ…

JAVA流程控制break,continue,goto

1.break在任何循环语句的主体成分&#xff0c;均可用break控制循环的流程。break用于强行退出循环&#xff0c;不执行循环中剩余的语句。&#xff08;break语句也在switch语句中使用&#xff09; 如图&#xff1a;break语句强行退出循环&#xff0c;结果输出1~30便结束&#xf…

两数之和-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第76讲。 两数之和&#xf…

Java面试八股之死锁和活锁的区别

死锁和活锁的区别 基本定义&#xff1a; 死锁&#xff08;Deadlock&#xff09;&#xff1a;指两个或多个线程互相等待对方释放资源&#xff0c;从而导致所有线程都无法继续执行的状态。每个线程至少持有一个资源&#xff0c;并等待另一个由其他线程持有的资源&#xff0c;形…