顺序表基本操作全面解析

news2024/10/3 8:25:52

文章目录

  • 1.线性表
  • 2.顺序表分类
    • 2.1 静态顺序表
    • 2.2 动态顺序表
  • 3. 顺序表各接口实现
    • 1. 定义结构体`(Seqlist)`
    • 2. 结构体初始化`(SLInit)`
    • 3.检查容量 `(SLCheckCapacity)`
    • 4.打印数据 `(SLPrintf)`
    • 5.插入操作
      • 5.1 从数据头部插入`(SLPushFront)`
      • 5.2 从数据尾部插入`(SLPushBack)`
      • 5.3 从任意下标位置的插入`(SLInsert)`
    • 6.删除操作
      • 6.1 从数据头部删除`(SLPopFront)`
      • 6.2 从数据尾部删除`(SLPopBack)`
      • 6.3 从任意下标位置的删除`(SLErase)`
    • 7 销毁操作 `(SLDestroy)`
  • 4.完整代码
    • 4.1 SeqList.h文件
    • 4.2 SeqList.c文件
    • 4.3 Test.c文件

1.线性表

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

案例:蔬菜分为绿叶类、瓜类、菌菇类。线性表指的是具有部分相同特性的一类数据结构的集合

2.顺序表分类

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

2.1 静态顺序表

静态顺序表概念:使用定长数组存储元素
缺点是定义空间小了不够用,定义大了浪费,不好把控。

在这里插入图片描述

2.2 动态顺序表

动态顺序表概念:使用动态开辟的数组存储。
动态顺序表 根据自己的需求调整大小,
在这里插入图片描述

3. 顺序表各接口实现

首先建立3个文件
1.SeqList.h头文件,用来声明函数
2.SeqList.c文件,用来定义函数
3.Test.c文件,用来测试函数

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

1. 定义结构体(Seqlist)

在SeqList.h头文件中

typedef int SLDataType;

typedef struct Seqlist
{
  SLDataType* a;
  int size;       // 有效数据
  int capacity;   // 空间容量
}SL;

2. 结构体初始化(SLInit)

注意下述代码皆是:
SeqList.h头文件中定义函数
SeqList.c文件中实现函数
Test.c文件中测试函数

SeqList.h文件中
定义函数:
在这里插入图片描述
SeqList.c文件中
实现函数:

 void SLInit(SL *ps)     // 数据表初始化
{
  assert(ps);
  ps->a = NULL;
  ps->size = 0;
  ps->capacity = 0;
}

Test.c文件中
测试函数:

int main()
{
  SL s1;
  SLInit(&s1);
  return 0;
}

调试结果:
在这里插入图片描述

3.检查容量 (SLCheckCapacity)

定义函数:
在这里插入图片描述
实现函数:

void SLCheckCapacity(SL* ps)  // 检查内存是否足够,不够就扩容。
{
	//一般情况为了避免频繁插入数据而增容,或者一下开辟很大的空间,我们一般是每次增容2倍
	assert(ps);
    if (ps->size == ps->capacity)
    {
      int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
      SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity);
      if (tmp == NULL)
      {
        perror("realloc fail");
        return;
      }
      ps->a = tmp;
      ps->capacity = newCapacity;
    }
}

测试函数:

int main()
{
  SL s1;
  SLInit(&s1);
  SLCheckCapacity(&s1);
  return 0;
}

调试结果:
在这里插入图片描述

4.打印数据 (SLPrintf)

定义函数:
在这里插入图片描述
实现函数:

void SLPrintf(SL* ps)   // 数据表打印
{
  assert(ps);
  for (int i = 0; i < ps->size; i++)
  {
    printf("%d ", ps->a[i]);
  }
  printf("\n");
}

5.插入操作

5.1 从数据头部插入(SLPushFront)

定义函数:
在这里插入图片描述
实现函数:

void SLPushFront(SL* ps, SLDataType x)  // 头插
{
  assert(ps);
  SLCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= 0)
  {
    ps->a[end + 1] = ps->a[end];
    end--;
  }
  ps->a[0] = x;
  ps->size++;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

5.2 从数据尾部插入(SLPushBack)

定义函数:
在这里插入图片描述
实现函数:

void SLPushBack(SL* ps, SLDataType x)   // 尾插
{
  assert(ps);
  SLCheckCapacity(ps);
  ps->a[ps->size++] = x;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

5.3 从任意下标位置的插入(SLInsert)

定义函数:
在这里插入图片描述

实现函数:

void SLInsert(SL* ps, int pos, SLDataType x)  // 任意下标位置的插入
{
  assert(ps);
  assert(pos >= 0 && pos <= ps->size);
  SLCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= pos)
  {
    ps->a[end + 1] = ps->a[end];
    end--;
  }
  ps->a[pos] = x;
  ps->size++;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

6.删除操作

6.1 从数据头部删除(SLPopFront)

定义函数:
在这里插入图片描述

实现函数:

void SLPopFront(SL* ps) // 头删
{
  assert(ps);
  assert(ps->size>0);
  int begin = 1;
  while (begin < ps->size)
  {
    ps->a[begin - 1] = ps->a[begin];
    begin++;
  }
  ps->size--;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

6.2 从数据尾部删除(SLPopBack)

定义函数:
在这里插入图片描述
实现函数:

void SLPopBack(SL* ps)  // 尾删
{
  assert(ps);
  assert(ps->size>0);
  ps->size--;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

6.3 从任意下标位置的删除(SLErase)

定义函数:
在这里插入图片描述

实现函数:

void SLErase(SL* ps, int pos)    // 任意下标位置的删除
{
  assert(ps);
  assert(pos >= 0 && pos < ps->size);   
  // 这里删除不能用等于ps->size,ps->size看作下标的话相当于下标的最后一个位置+1
  
  int begin = pos + 1;
  while (begin < ps->size)
  {
    ps->a[begin - 1] = ps->a[begin];
    begin++;
  }
  ps->size--;
}

动图解析:
在这里插入图片描述

测试函数结果:
在这里插入图片描述

7 销毁操作 (SLDestroy)

定义函数:
在这里插入图片描述

实现函数:

void SLDestroy(SL* ps)  // 数据表销毁
{
  assert(ps);
  if (ps->a != NULL)
  {
    free(ps->a);
    ps->a = NULL;
    ps->size = 0;
    ps->capacity = 0;
  }
}

在这里插入图片描述

4.完整代码

4.1 SeqList.h文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;

typedef struct Seqlist
{
  SLDataType* a;
  int size;       // 有效数据
  int capacity;   // 空间容量
}SL;

void SLInit(SL *ps);    // 数据表初始化
void SLDestroy(SL *ps); // 数据表销毁

void SLPushFront(SL* ps, SLDataType x); // 头插
void SLPushBack(SL *ps ,SLDataType x);  // 尾插

void SLPopFront(SL* ps);  // 头删
void SLPopBack(SL* ps);   // 尾删


void SLCheckCapacity(SL* ps); // 检查内存是否足够,不够就扩容。
void SLPrintf(SL* ps);  // 数据表打印

void SLInsert(SL* ps, int pos, SLDataType x);  //任意下标位置的插入
void SLErase(SL* ps, int pos);  //任意下标位置的删除

4.2 SeqList.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void SLCheckCapacity(SL* ps)  // 检查内存是否足够,不够就扩容。
{
    assert(ps);
    if (ps->size == ps->capacity)
    {
      int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
      SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity);
      if (tmp == NULL)
      {
        perror("realloc fail");
        return;
      }
      ps->a = tmp;
      ps->capacity = newCapacity;
    }
}

void SLPrintf(SL* ps)   // 数据表打印
{
  assert(ps);
  for (int i = 0; i < ps->size; i++)
  {
    printf("%d ", ps->a[i]);
  }
  printf("\n");
}


void SLInit(SL *ps)     // 数据表初始化
{
  assert(ps);
  ps->a = NULL;
  ps->size = 0;
  ps->capacity = 0;
}

void SLDestroy(SL* ps)  // 数据表销毁
{
  assert(ps);
  if (ps->a != NULL)
  {
    free(ps->a);
    ps->a = NULL;
    ps->size = 0;
    ps->capacity = 0;
  }
}

void SLPushFront(SL* ps, SLDataType x)  // 头插
{
  assert(ps);
  SLCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= 0)
  {
    ps->a[end + 1] = ps->a[end];
    end--;
  }
  ps->a[0] = x;
  ps->size++;
}

void SLPushBack(SL* ps, SLDataType x)   // 尾插
{
  assert(ps);
  SLCheckCapacity(ps);
  ps->a[ps->size++] = x;
}



void SLPopFront(SL* ps) // 头删
{
  assert(ps);
  assert(ps->size > 0);
  int begin = 1;
  while (begin < ps->size)
  {
    ps->a[begin - 1] = ps->a[begin];
    begin++;
  }
  ps->size--;
}

void SLPopBack(SL* ps)  // 尾删
{
  assert(ps);
  assert(ps->size>0);
  ps->size--;
}

// pos是下标
void SLInsert(SL* ps, int pos, SLDataType x)  // 任意下标位置的插入
{
  assert(ps);
  assert(pos >= 0 && pos <= ps->size);
  SLCheckCapacity(ps);
  int end = ps->size - 1;
  while (end >= pos)
  {
    ps->a[end + 1] = ps->a[end];
    end--;
  }
  ps->a[pos] = x;
  ps->size++;
}

void SLErase(SL* ps, int pos)    // 任意下标位置的删除
{
  assert(ps);
  assert(pos >= 0 && pos < ps->size);   // 这里删除不能用等于ps->size,ps->size看作下标的话相当于下标的最后一个位置+1
  int begin = pos + 1;
  while (begin < ps->size)
  {
    ps->a[begin - 1] = ps->a[begin];
    begin++;
  }
  ps->size--;
}

4.3 Test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void TestSL1()  // 头插,尾插
{
  printf("TestSL1:\n");
  SL s1;
  SLInit(&s1);
  SLPushFront(&s1, 10);
  SLPushBack(&s1, 30);
  SLPrintf(&s1);  
}

void TestSL2()  // 头删,尾删
{
  printf("TestSL2:\n");
  SL s1;
  SLInit(&s1);
  SLPushFront(&s1, 10);
  SLPushBack(&s1, 30);
  SLPushFront(&s1, 10);
  SLPushBack(&s1, 30);
  SLPrintf(&s1);
  SLPopBack(&s1);
  SLPopFront(&s1);
  SLPrintf(&s1);
}

void TestSL3()//任意下标位置的插入,删除测试
{
  printf("TestSL3:\n");
  SL s1;
  SLInit(&s1);
  SLPushFront(&s1, 10);
  SLPushBack(&s1, 30);
  SLPrintf(&s1);
  SLInsert(&s1, 1, 520);
  SLPrintf(&s1);
  SLErase(&s1, 2);
  SLPrintf(&s1);
}

int main()
{
  TestSL1();
  TestSL2();
  TestSL3();
}

运行结果如下:
在这里插入图片描述

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

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

相关文章

控制论与科学方法论

《控制论与科学方法论》&#xff0c;真心推荐。 书籍原文电子版PDF&#xff1a;https://pan.quark.cn/s/aa40d59295df&#xff08;分类在学习目录下&#xff09; 备用链接&#xff1a;https://pan.xunlei.com/s/VNgj2vjW-Hf_543R2K8kbaifA1?pwd2sap# 控制论是一种让系统按照我…

C#学习相关系列之Linq用法---group和join相关用法(三)

一、Group用法 在C#的LINQ中&#xff0c;Grou将集合中的元素按照指定的键进行分组。Group方法返回一个IEnumerable<IGrouping<TKey, TElement>>类型的集合&#xff0c;其中TKey表示分组的键类型&#xff0c;TElement表示集合中元素的类型。每个IGrouping<TKey, …

Java(四)(多态,final,常量,抽象类,接口)

目录 多态 基本概念: 使用多态的好处 类型转换 遇到的问题 解决方法 强制类型转换的一个注意事项 final 常量 抽象类 啥是个抽象类? 抽象类的注意事项,特点 抽象类的场景和好处 抽象类的常见应用场景: 模板方法设计模式 接口 基本概念 接口的好处 JDK8开始,接…

Java之API(上)

前言&#xff1a; 这一次内容主要是围绕Java开发中的一些常用类&#xff0c;然后主要是去学习这些类里面的方法。 一、高级API&#xff1a; (1)介绍&#xff1a;API指的是应用程序编程接口&#xff0c;API可以让编程变得更加方便简单。Java也提供了大量API供程序开发者使用&…

【华为OD题库-032】数字游戏-java

题目 小明玩一个游戏。系统发1n张牌&#xff0c;每张牌上有一个整数。第一张给小明&#xff0c;后n张按照发牌顺序排成连续的一行。需要小明判断&#xff0c;后n张牌中&#xff0c;是否存在连续的若干张牌&#xff0c;其和可以整除小明手中牌上的数字. 输入描述: 输入数据有多组…

NLP学习

参考&#xff1a;NLP发展之路I - 从词袋模型到Transformer - 知乎 (zhihu.com) NLP大致的发展历史。从最开始的词袋模型&#xff0c;到RNN&#xff0c;到Transformers和BERT&#xff0c;再到ChatGPT&#xff0c;NLP经历了一段不断精进的发展道路。数据驱动和不断完善的端到端的…

逻辑漏洞(业务逻辑)dami CMS

逻辑漏洞&#xff08;业务支付逻辑漏洞&#xff09;dami CMS 0x01 业务逻辑简介 业务逻辑指的是一个系统或应用程序中的实际业务规则和流程。它描述了如何处理特定的业务需求、数据和操作。业务逻辑通常是根据特定行业或组织的需求而设计的。 在软件开发中&#xff0c;业务逻…

Matplotlib颜色条的配置_Python数据分析与可视化

Matplotlib颜色条配置 基本颜色颜色条选择配色方案颜色条刻度的限制与扩展功能的设置离散型颜色条 基本颜色 Matplotlib提供了8种指定颜色的方法&#xff1a; 在[0&#xff0c;1]中的浮点值的RGB或RGBA元组&#xff08;例如 (0.1, 0.2, 0.5) 或&#xff08;0.1&#xff0c; 0.…

MacOS 成为恶意软件活动的目标

Malwarebytes 警告称&#xff0c;一个针对 Mac 操作系统 (OS) 的数据窃取程序正在通过虚假的网络浏览器更新分发给毫无戒心的目标。 Atomic Stealer&#xff0c;也称为 AMOS&#xff0c;是 Mac OS 上流行的窃取程序。 Atomic Stealer (AMOS) 恶意软件最近被发现使用“ClearFa…

使用websocket获取thingsboard设备的实时数据

背景 有一个读者前来咨询,如何实时获取设备的遥测数据。 其实tb是有提供websocket接口来获取设备数据的。而且还支持js跨域调用。下面给大家演示一下。 websocket地址 完整代码 <!DOCTYPE HTML> <html><h

2023亚太杯数学建模赛题人工精准翻译

大家好&#xff0c;亚太杯今天早上6点已经开赛啦&#xff0c;然后我在这里给大家带来赛题的精准人工翻译&#xff0c;防止大家直接用软件翻译导致某些地方乱码或者翻译不精准&#xff0c;这会导致后续做题过程出现很大偏差。 注意&#xff0c;以下翻译均免费发放word形式的哈&…

自学成为android framework高手需要准备哪些装备-千里马车载车机系统开发学习

背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;经常有很多学员买课同学都会问到需要准备哪些装备&#xff0c;我也回答了很多学员了&#xff0c;今天就搞一篇文章来统一说明一下&#xff0c;告诉一下大家如果你想从一个framework新手变成一个framework开发的高…

【精选】CSS入门必看知识点大合集

CSS简介 CSS概念 CSS&#xff08;Cascading Style Sheets&#xff09;层叠样式表&#xff0c;又叫级联样式表&#xff0c;简称样式表 CSS文件后缀名为.css CSS用于HTML文档中元素样式的定义 为什么需要CSS 使用css的唯一目的就是让网页具有美观一致的页面 语法 CSS 规则…

VS Code 如何搭建C/C++环境

目录 一、VS Code是什么&#xff1f; 二、VS Code下载和安装 2.1下载 2.2安装 2.3环境介绍 三、Vs Code配置C/C环境 3.1下载和配置MinGW-w64编译器套件 3.1.1下载 3.1.2配置 一、VS Code是什么&#xff1f; 跨平台&#xff0c;免费且开源的现代轻量级代码编辑器 Vis…

vivado产生报告阅读分析15-时序报告11

Report Clock Domain Crossings “ Clock Domain Crossings (CDC) ” &#xff08; 时钟域交汇 &#xff09; 报告可对设计中的时钟域交汇执行结构分析。此信息可用于识别潜在不安全的 CDC &#xff0c; 此类 CDC 可能导致亚稳态或数据一致性问题。虽然 CDC 报告与“ Clock …

C#,数值计算——插值和外推,多项式插值与外推插值(Poly_interp)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 多项式插值与外推插值 /// Polynomial Interpolation and /// Extrapolation interpolation routines for one dimension /// </summary> public class Poly…

Rust错误处理:Result

文章目录 简介错误匹配 Rust基础教程&#xff1a; 初步⚙ 所有权⚙ 结构体和枚举类⚙ 函数进阶⚙ 泛型和特征⚙ 并发和线程通信⚙ cargo包管理⚙ 可空类型Option Rust进阶教程&#xff1a; 用宏实现参数可变的函数⚙ 类函数宏 简介 Rust中没有提供类似try…catch之类…

排序算法--希尔排序

实现逻辑 ① 先取一个小于n的整数d1作为第一个增量&#xff0c;把文件的全部记录分成d1个组。 ② 所有距离为d1的倍数的记录放在同一个组中&#xff0c;在各组内进行直接插入排序。 ③ 取第二个增量d2小于d1重复上述的分组和排序&#xff0c;直至所取的增量dt1(dt小于dt-l小于……

2023 年 亚太赛 APMCM (B题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 问题一&#xff1a; 建立没有作物的玻璃温室内的温度和风速分…