数据结构——顺序表(C语言实现)

news2025/4/22 18:31:18

1.顺序表的概述

1.1 顺序表的概念及结构

        在了解顺序表之前,我们要先知道线性表的概念,线性表,顾名思义,就是一个线性的且具有n个相同类型的数据元素的有限序列,常见的线性表有顺序表、链表、栈、队列、字符串等等。线性表的逻辑结构是线性的,也就是一条连续的直线,但它在物理结构上不一定是线性的,比如链表,你可以将它理解为串着很多个珠子的手串,每个珠子都是一个存储数据的节点,但这些珠子在内存中的存储不一定是连续的。

        而我们今天提到的顺序表,它则是逻辑结构和物理结构都是一致的,因为顺序表的底层结构是数组,而数组我们之前提过,它在内存中的存储是连续的。

1.2 顺序表的分类 

        顺序表可以分为静态顺序表和动态顺序表,接下来就让我们通过代码来看看这二者有何区别:

//静态顺序表
struct SeqList
{
  SLDataType a[N]; //定长数组
  int size;        //有效数据个数
};

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

 从上面的代码我们可以看出,静态顺序表和动态顺序表的最大区别在于他们存储数据的底层结构,静态顺序表是一个定长数组,在存储数据时,我们不好把握这个定长数组的长度,如果给定的长度太小,就不够存放,给定的长度太大,又会造成空间浪费。而动态顺序表是一个动态数组(可以通过malloc或realloc动态申请一块连续空间),这样的好处是我们可以按需申请空间,既不会造成很大的空间浪费,也不会出现不够存放的情况。

那接下来就让我们一起来实现动态顺序表。

2.动态顺序表的实现

首先我们先在头文件中定义好动态顺序表的结构以及声明所需要的函数接口。

//头文件SeqList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1  // scanf函数在vs中是不安全的
#include<stdio.h>
#include<stdlib.h>                 
#include<assert.h>



typedef int SLDataType; //这里是方便后续需要修改顺序表数据类型

//动态顺序表
typedef struct SeqList
{
	SLDataType* arr; //存储数据的底层结构
	int capacity;   //记录顺序表的空间大小
	int size;       //记录顺序表当前有效的数据个数
}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 SLPopFront(SL* ps);
//尾删
void SLPopBack(SL* ps);


//指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除
void SLErase(SL* ps, int pos);


//查找
int SLFind(SL* ps, SLDataType x);

接下来我们就需要在.c文件中将这些函数一一实现咯

//SeqList.c文件

#include"SeqList.h"   //首先要包含我们先前创建的头文件



//初始化   数组置空,有效数据个数和顺序表空间容量都置0
//这里的ps是我们创建好的顺序表的指针
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}


//销毁  释放内存,置空,有效数据个数和顺序表空间容量都置0
void SLDestroy(SL* ps) {
	if (ps->arr) {
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}


//判断顺序表当前是否需要扩容
void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)//如果当前有效数据个数等于顺序表空间容量,则说明需要
	{   
        //三目操作符,如果容量为0,则返回4的初始容量,否则就扩容两倍
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
        //创建一个临时变量来存放新申请的空间
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
        //申请空间失败
		if (tmp == NULL) {
			perror("realloc error!");
			exit(1);
		}
		//扩容成功
		ps->arr = tmp;//新申请到的空间赋值给数组
		ps->capacity = newCapacity;//更新容量
	}
}

//打印顺序表
void SLPrint(SL* ps)
{    
    //遍历数组
	for (int i = 0;i < ps->size;i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
}

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	//断言
	assert(ps != NULL);
	//空间不够,扩容
	SLCheckCapacity(ps);
	//空间足够,直接插入
	ps->arr[ps->size++] = x;
}
//头插
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 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 SLPopBack(SL* ps)
{
	//无数据
	assert(ps);
	assert(ps->size);
	//有数据
	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(ps->size);
	assert(pos >= 0 && pos <= ps->size);
	for (int i = pos;i<ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}


//查找
int SLFind(SL* ps, SLDataType x)
{

	assert(ps);
	for (int i = 0;i < ps->size;i++)
	{
		if (ps->arr[i] == x) {
			return i;
		}
	}
	return -1;
}

3.动态顺序表功能测试

 新创建一个main.c文件,用于测试顺序表功能

//main.c文件

#include"SeqList.h"

int main()
{
	//创建一个顺序表
    SL sl;
    //初始化顺序表
    SLInit(&sl);
    //尾插2 3
    SLPushBack(&sl,2);
    SLPushBack(&sl,3);
    SLPushBack(&sl,4);
    //打印顺序表,此时应打印2 3 4
    SLPrint(&sl);

    //头插0 1
    SLPushFront(&sl,1);
    SLPushFront(&sl,0);
    //打印顺序表,此时应打印0 1 2 3 4
    SLPrint(&sl);

    //头删顺序表
    SLPopFront(&sl);
    //打印顺序表,此时应打印1 2 3 4
    SLPrint(&sl);

    //尾删顺序表
    SLPopBack(&sl);
    //打印顺序表,此时应打印1 2 3
    SLPrint(&sl);

    //在2前面插入0
    SLInsert(&sl,SLFind(&sl,2),0);
    //打印顺序表,此时应打印1 0 2 3
    SLPrint(&sl);

    //删掉0
    SLErase(&sl,SLFind(&sl,0));
    //打印顺序表,此时应打印1 2 3
    SLPrint(&sl);

    //销毁顺序表
    SLDestroy(&sl);
	return 0;
}

运行结果:

 

可以看到,打印的结果和我们预测的一致。

顺序表的实现就讲到这里了,有什么疑问可以在评论区提出,看到一定会回复。

有什么错误的地方欢迎指出。

如果你觉得这篇文章对你有帮助的话,麻烦动动小手点个赞~ 

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

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

相关文章

STP原理与配置以及广播风暴实验STP实验

学习目标 环路引起的问题 掌握STP的工作原理 掌握STP的基本配置 STP的配置 环路引起的问题 一、广播风暴&#xff08;Broadcast Storm&#xff09; 问题原理&#xff1a; 交换机对广播帧&#xff08;如 ARP 请求、DHCP 发现报文&#xff09;的处理方式是洪泛&#xff0…

网络不可达network unreachable问题解决过程

问题&#xff1a;访问一个环境中的路由器172.16.1.1&#xff0c;发现ssh无法访问&#xff0c;ping发现回网络不可达 C:\Windows\System32>ping 172.16.1.1 正在 Ping 172.16.1.1 具有 32 字节的数据: 来自 172.16.81.1 的回复: 无法访问目标网。 来自 172.16.81.1 的回复:…

力扣经典拓扑排序

207. 课程表&#xff08;Course Schedule&#xff09; 你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。先修课程按数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表…

【第16届蓝桥杯C++C组】--- 2025

hello呀&#xff0c;小伙伴们&#xff0c;这是第16届蓝桥杯第二道填空题&#xff0c;和第一道填空题一样也是十分基础的题目&#xff0c;有C语言基础基本都可以解&#xff0c;下面我讲讲我当时自己的思路和想法&#xff0c;如果你们有更优化的代码和思路&#xff0c;也可以分享…

前端基础之《Vue(7)—生命周期》

一、什么是生命周期 1、生命周期 组件从“生”到“死”的全过程。 每一个组件都有生命周期。 2、生命周期四大阶段 创建阶段&#xff1a;beforeCreate、created 挂载阶段&#xff1a;beforeMount、mounted 更新阶段&#xff1a;beforeUpdate、updated 销毁阶段&#xff1a;be…

C语言高频面试题——指针数组和数组指针

指针数组和数组指针是 C/C 中容易混淆的两个概念&#xff0c;以下是详细对比&#xff1a; 1. 指针数组&#xff08;Array of Pointers&#xff09; 定义&#xff1a;一个数组&#xff0c;其元素是 指针类型。语法&#xff1a;type* arr[元素个数]; 例如&#xff1a;int* ptr_a…

Linux服务器配置Anaconda环境、Pytorch库(图文并茂的教程)

引言&#xff1a;为了方便后续新进组的 师弟/师妹 使用课题组的服务器&#xff0c;特此编文&#xff08;ps&#xff1a;我导从教至今四年&#xff0c;还未招师妹&#xff09; ✅ NLP 研 2 选手的学习笔记 笔者简介&#xff1a;Wang Linyong&#xff0c;NPU&#xff0c;2023级&a…

Android端使用无障碍服务实现远程、自动刷短视频

最近在做一个基于无障碍自动刷短视频的APP&#xff0c;需要支持用任意蓝牙遥控器远程控制&#xff0c; 把无障碍服务流程大致研究了一下&#xff0c;从下面3个部分做一下小结。 1、需要可调整自动上滑距离和速度以适配不同的屏幕和应用 智能适配99%机型&#xff0c;滑动参数可…

搭建用友U9Cloud ERP及UAP IDE环境

应用环境 Microsoft Windows 10.0.19045.5487 x64 专业工作站版 22H2Internet Information Services - 10.0.19041.4522Microsoft SQL Server 2019 - 15.0.2130.3 (X64)Microsoft SQL Server Reporing Services 2019 - 15.0.9218.715SQL Server Management Studio -18.6 laster…

多模态大语言模型arxiv论文略读(二十九)

Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文标题&#xff1a;Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文作者&#xff1a;Li Su…

卷积神经网络(CNN)详解

文章目录 引言1.卷积神经网络&#xff08;CNN&#xff09;的诞生背景2.卷积神经网络&#xff08;CNN&#xff09;介绍2.1 什么是卷积神经网络&#xff1f;2.2 卷积神经网络&#xff08;CNN&#xff09;的基本特征2.2.1 局部感知&#xff08;Local Connectivity&#xff09;2.2.…

【SF顺丰】顺丰开放平台API对接(注册、API测试篇)

1.注册开发者账号 注册地址&#xff1a;顺丰企业账户中心 2.登录开发平台 登录地址&#xff1a;顺丰开放平台 3.开发者对接 点击开发者对接 4.创建开发对接应用 开发者应用中“新建应用”创建应用&#xff0c;最多创建应用限制数量5个 注意&#xff1a;需要先复制保存生产校验…

VisualSVN过期后的解决方法

作为一款不错的源代码管理软件&#xff0c;svn还是有很多公司使用的。在vs中使用svn&#xff0c;大家一般用的都是VisualSVN插件。在30天试用期过后&#xff0c;它就不能被免费使用了。下面给大家讲如何免费延长过期时间&#xff08;自定义天数&#xff0c;可以设定一个很大的值…

DeepSeek智能时空数据分析(二):3秒对话式搞定“等时圈”绘制

序言&#xff1a;时空数据分析很有用&#xff0c;但是GIS/时空数据库技术门槛太高 时空数据分析在优化业务运营中至关重要&#xff0c;然而&#xff0c;三大挑战仍制约其发展&#xff1a;技术门槛高&#xff0c;需融合GIS理论、SQL开发与时空数据库等多领域知识&#xff1b;空…

STM32学习2

一、OLED 1.1 OLED介绍 OLED&#xff08;Organic Light Emitting Diode&#xff09;&#xff1a;有机发光二极管 OLED显示屏&#xff1a;性能优异的新型显示屏&#xff0c;具有功耗低、相应速度快、宽视角、轻薄柔韧等特点 0.96寸OLED模块&#xff1a;小巧玲珑、占用接口少…

LabVIEW液压系统远程监控与故障诊断

开发了一种基于LabVIEW的远程液压系统监控解决方案&#xff0c;通过先进的数据采集与分析技术&#xff0c;有效提升工程机械的运作效率和故障响应速度。该系统结合现场硬件设备和远程监控软件&#xff0c;实现了液压系统状态的实时检测和故障诊断&#xff0c;极大地提升了维护效…

Idea中实用设置和插件

目录 一、Idea使用插件 1.Fitten Code智能提示 2.MyBatisCodeHelperPro 3.HighlightBracketPair‌ 4.Rainbow Brackets Lite 5.GitToolBox(存在付费) 6.MavenHelperPro 7.Search In Repository 8.VisualGC(存在付费) 9.vo2dto 10.Key Promoter X 11.CodeGlance…

Java写数据结构:栈

1.概念&#xff1a; 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&#xff1a;栈的插…

机器学习-08-推荐算法-案例

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中关联规则 参考 机器学习&#xff08;三&#xff09;&#xff1a;Apriori算法&#xff08;算法精讲&#xff09; Apriori 算法 理论 重点 MovieLens:一个常用的电影推荐系统领域的数据集 23张图&#x…

LLM中的N-Gram、TF-IDF和Word embedding

文章目录 1. N-Gram和TF-IDF&#xff1a;通俗易懂的解析1.1 N-Gram&#xff1a;让AI学会"猜词"的技术1.1.1 基本概念1.1.2 工作原理1.1.3 常见类型1.1.4 应用场景1.1.5 优缺点 1.2 TF-IDF&#xff1a;衡量词语重要性的尺子1.2.1 基本概念1.2.2 计算公式1.2.3 为什么需…