数据结构与算法(C语言版)P2---线性表之顺序表

前景回顾

数据结构
数据的逻辑结构
数据的存储结构
数据的运算
线性结构
非线性结构
线性表
队列
字符串,数组,广义表
树形结构
图形结构
索引,排序,插入,删除,修改等

1、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的一条直线。但在物理结构上并不一定是连续的,线性表在物理上存储时,通常以__数组__和__链式结构__的形式存储。

顺序表本质上就是数组。

在这里插入图片描述

2、顺序表

2.1、概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删改查。

顺序表就是数组,但是在数组的基础上,它还要求数据是从头开始存储并且是连续存储的,不能跳跃间隔。

顺序表一般可以分为:

1、静态顺序表:使用固定长数组存储元素。

在这里插入图片描述

2、动态顺序表:使用动态开辟的数组存储。

在这里插入图片描述

3、顺序表的实现

【说明】:这里使用动态数组来实现顺序表。

顺序表主要有以下几个接口功能:

  • 打印(SeqListPrint)
  • 结构体初始化(SeqListInit)
  • 释放空间(SeqListDestory)
  • 检查扩容(SeqListCheckCapacity)
  • 头插(SeqListPushBack)
  • 头删(SeqListPopBack)
  • 尾插(SeqListPushFront)
  • 尾删(SeqListPopFront)
  • 查找元素(SeqListFind)
  • 在指定pos下标位置插入元素(SeqListInsert)
  • 删除pos位置的数据(SeqListErase)

3.1、定义结构体

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;typedef struct SeqList
{SLDataType* a;int size;int capacity;
}SL;

a指针变量表示需要动态开辟的数组。
size变量表示数组中有效数据个数。
capacity变量表示动态开辟数组的空间大小。

3.2、结构体初始化接口实现

//结构体初始化
void SeqListInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}

3.3、检查扩容接口实现

因为我们采用动态开辟数组的形式来实现顺序表,所以当我们在进行任何一个插入操作时,都需要先申请空间,以便数据的插入。
这里有几种情况需要我们处理:

  • 整个顺序表没有空间,扩容
  • 空间不够,扩容。
  • 空间足够,直接插入数即可。
void SeqListCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}
}

3.4、头插接口实现

void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}

头插的核心思想:将全体数据元素向后移动。比如现在有数组int b = [1,2,3,4,5],现在想头插数据6,可以采取这样的方法:把1,2,3,4,5全部整体向后移一位。然后再把6进行头插。

3.5、打印接口实现

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

3.6、销毁接口实现

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

3.7、头删接口实现

void SeqListPopFront(SL* ps)
{//这里需要加个判断,判断size是否>0,否则防止越界访问if (ps->size > 0){int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;}
}

头删核心思想:把数组中下标为1到下标为最后一个的所有元素全部向前移动。

3.8、尾插接口实现

void SeqListPushBack(SL* ps, SLDataType x)
{//先检查扩容SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}

3.9、尾删接口实现

void SeqListPopBack(SL* ps)
{if (ps->size > 0){ps->size--;}
}

3.10、查询指定元素

//查询指定元素,并返回下标
int SeqListFind(SL* ps, SLDataType x)
{for (int i = 0; i < ps->size; i++){if (x == ps->a[i]){return i;}}return -1;
}

3.11、在指定pos下标位置插入

void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 && ps->size >= pos);SeqListCheckCapacity(ps);int end = ps->size - 1;while (pos <= end){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}

3.12、删除pos下标位置的数据

void SeqListErase(SL* ps, int pos)
{assert(pos >= 0 && ps->size > pos);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}

以上就是使用动态数组实现顺序表的过程。下面展示全代码。

4、全代码展示

这里使用三个文件:

  • seqlist.h:用于结构体、各种函数接口的声明。
  • seqlist.c:用于各种函数接口的定义。
  • test.c:用于创建顺序表,实现顺序表。

4.1、seqlist.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;typedef struct SeqList
{SLDataType* a;int size;int capacity;
}SL;//结构体初始化
void SeqListInit(SL* ps);//检查扩容
void SeqListCheckCapacity(SL* ps);//头插
void SeqListPushFront(SL* ps, SLDataType x);//打印
void SeqListPrint(SL* ps);//销毁
void SeqListDestroy(SL* ps);//头删
void SeqListPopFront(SL* ps);//尾插
void SeqListPushBack(SL* ps, SLDataType x);//尾删
void SeqListPopBack(SL* ps);//查询指向元素,并返回下标
int SeqListFind(SL* ps, SLDataType x);//在指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);//删除pos下标位置的数据
void SeqListErase(SL* ps, int pos);

4.2、seqlist.c

#include "list.h"//结构体初始化
void SeqListInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}//检查扩容
void SeqListCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}
}//头插
void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}//打印
void SeqListPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}//销毁
void SeqListDestroy(SL* ps)
{free(ps->a);ps->a = NULL;ps->size = ps->capacity =  0;
}//头删
void SeqListPopFront(SL* ps)
{//这里需要加个判断,判断size是否>0,否则防止越界访问if (ps->size > 0){int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;}
}//尾插
void SeqListPushBack(SL* ps, SLDataType x)
{//先检查扩容SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}//尾删
void SeqListPopBack(SL* ps)
{if (ps->size > 0){ps->size--;}
}//扩展接口
//查询指定元素,并返回下标
int SeqListFind(SL* ps, SLDataType x)
{for (int i = 0; i < ps->size; i++){if (x == ps->a[i]){return i;}}return -1;
}//在指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 && ps->size >= pos);SeqListCheckCapacity(ps);int end = ps->size - 1;while (pos <= end){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}//删除pos下标位置的数据
void SeqListErase(SL* ps, int pos)
{assert(pos >= 0 && ps->size > pos);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}

4.3、test.c

#include "list.h"int main()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl, 1);SeqListPushFront(&sl, 2);SeqListPushFront(&sl, 3);int pos = SeqListFind(&sl, 2);SeqListErase(&sl, pos);SeqListPrint(&sl);SeqListDestroy(&sl);return 0;
}

5、顺序表的优缺点

顺序表的缺陷:

  • 空间不够了需要扩容,扩容是需要付出代价的。
  • 避免频繁的扩容,我们满了基本都是扩2倍。这可能就会导致一定空间的浪费。
  • 顺序表要求数据从开始位置连续存储,那么我们在头部或者中间位置插入、删除数据就需要挪动数据,有性能消耗,效率不高。

顺序表的优点:

  • 支持随机访问。
  • 存储密度大

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

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

相关文章

安全基础 --- nodejs沙箱逃逸

nodejs沙箱逃逸 沙箱绕过原理&#xff1a;沙箱内部找到一个沙箱外部的对象&#xff0c;借助这个对象内的属性即可获得沙箱外的函数&#xff0c;进而绕过沙箱 前提&#xff1a;使用vm模块&#xff0c;实现沙箱逃逸环境。&#xff08;vm模式是nodejs中内置的模块&#xff0c;是no…

WebGIS面试题(浙江中海达)

1、Cesium中有几种拾取坐标的方式&#xff0c;分别介绍 Cesium是一个用于创建3D地球和地理空间应用的JavaScript库。在Cesium中&#xff0c;你可以使用不同的方式来拾取坐标&#xff0c;以便与地球或地图上的对象进行交互。以下是Cesium中几种常见的拾取坐标的方式&#xff1a…

微服务学习(七):docker安装Mysql

微服务学习&#xff08;七&#xff09;&#xff1a;docker安装Mysql 1、拉取镜像 docker pull mysql2、查看安装的镜像 docker images3、安装mysql docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \…

TensorFlow安装 ,在原本的虚拟环境下配置Tensorflow.

1.TensorFlow安装 &#xff0c;在原本的虚拟环境下配置Tensorflowh和pytorch 2.我首先在anaconda的环境下创建了一个tensorflow文件夹 如何先进入D盘&#xff0c;再进入tensorflow文件夹的目录D:cd D:\Anaconda\TensorFlowSoftWarepip install tensorflow如图所示报错解决方法 …

Antdesign 4中让分页组件居中显示的方法

在Ant Design 4中分页组件默认是最右边显示的&#xff0c;而这个没有设置位置的属性的 解决办法&#xff1a; 在pagination的属性中增加&#xff1a; style: {textAlign: "center"} 在Ant Design 5中可以让pagination使用align: center来实现分页组件居中

小程序中如何查看会员的访问记录

​在小程序中&#xff0c;我们可以通过如下方式来查看会员的访问记录。下面是具体的操作流程&#xff1a; 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要查看访客记录的会员卡。也支持对会员卡按卡号、手机号和等级进行搜索。 2. 查看会员卡详情。点…

【自然语言处理】【大模型】MPT模型结构源码解析(单机版)

相关博客 【自然语言处理】【大模型】MPT模型结构源码解析(单机版) 【自然语言处理】【大模型】ChatGLM-6B模型结构代码解析(单机版) 【自然语言处理】【大模型】BLOOM模型结构源码解析(单机版) 【自然语言处理】【大模型】极低资源微调大模型方法LoRA以及BLOOM-LORA实现代码 【…

Cesium 空间量算——生成点位坐标

文章目录 需求分析1. 点击坐标点实现2. 输入坐标实现 需求 用 Cesium 生成点位坐标&#xff0c;并明显标识 分析 以下是我的两种实现方式 第一种是坐标点击实现 第二种是输入坐标实现 1. 点击坐标点实现 //点位坐标getLocation() {this.hoverIndex 0;let that this;this.view…

【链表】排序链表-力扣148题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

思维链(Chain-of-Thought Prompting Elicits Reasoning in Large Language Models)

概括 论文主要描述了一种用思维链的提升LLM模型推理能力的方式&#xff0c;并且通过实验的方式&#xff0c;证明了思维链在算术、常识和符号等任务方面的显著效果。仅通过540B大小的PaLM模型&#xff0c;通过8个思维链样例就可以实现在GSM8K上的sota效果。 具体工作 这篇论文…

OpenGLES:使用纹理绘制一张图片

一.概述 最近疏于写博客&#xff0c;接下来会陆续更新这段时间OpenGLES的一些开发过程。 前两篇OpenGLES的博客讲解了怎样使用OpenGLES实现相机普通预览和多宫格滤镜 在相机实现过程中&#xff0c;虽然使用到了纹理&#xff0c;但只是在生成一个纹理之后&#xff0c;使用纹理…

精华回顾:Web3 前沿创新者在 DESTINATION MOON 共话未来

9 月 17 日&#xff0c;由 TinTinLand 主办的「DESTINATION MOON: Web3 Dev Summit Shanghai 2023」线下活动在上海黄浦如约而至。 本次 DESTINATION MOON 活动作为 2023 上海区块链国际周的 Side Event&#xff0c;设立了 4 场主题演讲与 3 个圆桌讨论&#xff0c;聚集了诸多…

Goby 漏洞发布|Revive Adserver 广告管理系统 adxmlrpc.php 文件远程代码执行漏洞(CVE-2019-5434)

漏洞名称&#xff1a;Revive Adserver 广告管理系统 adxmlrpc.php 文件远程代码执行漏洞&#xff08;CVE-2019-5434&#xff09; English Name&#xff1a; Revive Adserver adxmlrpc.php Remote Code Execution Vulnerability (CVE-2019-5434) CVSS core: 9.0 影响资产数&a…

【自学记录】深度学习入门——基于Python的理论与实现(第3章 神经网络)

3.4.3 3层神经网络Python实现 实现的是这个网络 **init_network()**函数会进行权重和偏置的初始化&#xff0c;并将它们保存在字典变量network中。这个字典变量network中保存了每一层所需的参数(权重和偏置)。 **forward()**函数中则封装了将输入信号转换为输出信号的处理过程…

ReadPaper论文阅读工具

之前看文献一直用的EndNote嘛&#xff0c;但是突然发现了它的一个弊端&#xff0c;就是说每次没看完退出去之后&#xff0c;下次再接着看的时候它不能保留我上一次的位置信息&#xff0c;又要重头开始翻阅&#xff0c;这让我感到很烦躁哈哈。&#xff08;当然也不知道是不是我哪…

MySQL数据库简介+库表管理操作+数据库用户管理

Mysql Part 1 一、数据库的基本概念1.1 使用数据库的必要性1.2 数据库基本概念1.2.1 数据&#xff08;Data&#xff09;1.2.2 表1.2.3 数据库1.2.4 数据库管理系统&#xff08;DBMS&#xff09;1.2.5 数据库系统 1.3 数据库的分类1.3.1 关系数据库 SQL1.3.2 非关系数据库 NoSQL…

C语言自定义类型详解(1)结构体知识汇总

本篇概要 本篇主要讲述C语言结构体的相关知识&#xff0c;包括结构体的基本声明&#xff0c;结构体的匿名结构&#xff0c;结构体的自引用&#xff0c;结构体变量的定义和初始化以及结构体的内存对齐等相关知识。 文章目录 本篇概要1.结构体1.1结构体的基本声明1.2结构体的特殊…

[SQL Server]在应使用条件的上下文(在 ‘)‘ 附近)中指定了非布尔类型的表达式,查询时间大于某个数值时

这种条件查询条件里面不要有空格&#xff0c;一个也不要有 这种条件查询条件里面不要有空格&#xff0c;一个也不要有 $giftsDb::table(drawgot)->where(disabtime,<,"2030-01-03")->select();

合肥先进光源国家重大科技基础设施项目及配套工程启动会纪念

合肥先进光源国家重大科技基础设施项目及配套工程启动会纪念 卡西莫多 合肥长丰岗集里 肥鸭从此别泥塘 先平场地设围栏 进而工地筑基忙 光阴似箭指日争 源流汇智山水长 国器西北扩新地 家校又添新区园 重器托举有群力 大步穿梭两地间 科教兴邦大国策 技术盈身坦荡行…

【数据结构】—交换排序之快速排序究极详解,手把手带你从简单的冒泡排序升级到排序的难点{快速排序}(含C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;靴の花火—ヨルシカ 0:28━━━━━━️&#x1f49f;──────── 5:03 …