【数据结构】线性表之——“顺序表”

news2025/5/22 22:47:34

文章目录

  • 前言
  • 顺序表主体结构
  • 顺序表操作函数介绍
  • 顺序表操作函数实现
    • 实现顺序:
    • 顺序表的初始化:
    • 顺序表插入函数:
      • 头插
      • 尾插
      • 指定位置插入
    • 顺序表打印函数
    • 查找顺序表数据
    • 顺序表删除函数
      • 头删
      • 尾删
      • 指定位置删除
    • 修改顺序表
    • 销毁顺序表
  • 文件分类
    • test.c
    • SeqList.c
    • SeqList.h
  • 撒花


前言

  • 为什么有顺序表?由于数组定义之后不能扩充,我们需要一种更方便的结构来装载数据,顺序表诞生了。
  1. 顺序表是线性表的一种,线性表的存储都是形成一条线的,顺序表不仅仅在逻辑上是用一条线链接,在内存中也是连续的一块空间,因此可以进行下标随机访问
  2. 顺序表不同于数组,顺序表在空间不够的情况下可以选择进行扩充
  3. 顺序表不同于数组,顺序表开辟在堆空间中,不用担心栈空间不够用。
  4. 相对麻烦的就是,先对顺序表进行操作必须要自己实现增删改查等函数。
  5. 如果学会了顺序表可以试着自主完成通讯录小程序⭐

PS:需要源码直接通过目录跳转到最后

顺序表主体结构

默认大小与扩容大小还有类型都可以是任意大小或类型

#define SLDataType int
#define DEFAULT_SZ 5			//默认大小
#define DEFAULT_INC 3			//默认扩容大小

typedef struct SeqList
{
	SLDataType* data;
	int sz;
	int capable;
}SeqList;

在这里插入图片描述

用define定义数据可以方便修改

顺序表操作函数介绍

  1. void SLInit(SeqList* SL); 顺序表初始化
  2. void SLprint(SeqList* SL); 打印顺序表
  3. void SLPushFront(SeqList* SL, SLDataType x); 顺序表投插
  4. void SLPushBack(SeqList* SL, SLDataType x); 顺序表尾插
  5. void SLPopFront(SeqList* SL); 顺序表头删
  6. void SLPopBack(SeqList* SL); 顺序表尾删
  7. void SLInsert(SeqList* SL, int pos, SLDataType x); ~指定位置插入
  8. void SLEarse(SeqList* SL, int pos); 指定位置删除
  9. int SLFind(SeqList* SL, SLDataType x); 查找指定数据下标
  10. void SLModify(SeqList* SL, int pos, SLDataType x); 修改指定位置数据
  11. void SLDestroy(SeqList* SL); 清楚数据包

为了代码方便阅读,讲顺序表操作函数全部放在Seqlist.c文件中,将头文件放在SeqList.h,测试文件test.c 🌞

顺序表操作函数实现

实现顺序:

为了方便调试,建议每写完1-2个函数就进行测试,初始化之后,首先实现print函数可以方便我们进行调试,建议按照顺序,插入-》打印-》查找-》删除-》销毁顺序表函数。

顺序表的初始化:

void SLInit(SeqList* SL)
{
	assert(SL);				//assert防止传进来的指针为空,进行断言
	SL->capable = DEFAULT_SZ;
	SL->sz = 0;
	int* ptr = malloc(sizeof(int) * DEFAULT_SZ);	//为顺序表开辟一段空间
	if (ptr == NULL)								//预防开辟失败进行判断
	{
		perror("malloc:");
	}
	SL->data = ptr;
	printf("初始化成功\n");
}

必须先进性初始化,给顺序表开辟一个堆空间,并对其默认长度与默认最大长度进行初始化。

顺序表插入函数:

头插

头插从第一个位置插入,其余函数按顺序向后移动一格,

  • 既然有插入就一定会有空间不够用的问题,这里用到检查空间是否够用的一个函数
void CheckSL(SeqList* SL)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	if (SL->sz == SL->capable)		//如果当前大小等于当前最大大小那么进行扩容
	{
		int* ptr = NULL;
		ptr = (int*)realloc(SL->data, sizeof(int) * (SL->capable + DEFAULT_INC));
		if (ptr == NULL)
		{
			perror("check:realloc:");
		}
		SL->data = ptr;
		SL->capable += DEFAULT_INC;
		printf("扩容成功\n");
	}
}

头插函数

  • 将所有数据向后移动,注意要从后面开始移动,不然数据会被覆盖掉

在这里插入图片描述

void SLPushFront(SeqList* SL, SLDataType x)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	CheckSL(SL);
	int end = SL->sz - 1;
	while (end >= 0)		//将所有数据向后移动,注意要从后面开始移动,不然数据会被覆盖掉
	{
		SL->data[end + 1] = SL->data[end];
		end--;
	}
	SL->data[0] = x;		//所有数据都向后移动之后进行头插
	SL->sz++;				//当前大小+1
}

尾插

从最后进行插入数据

  • 尾插也会用到检查空间是否够用的函数,这里不重复了
void SLPushBack(SeqList* SL,SLDataType x)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	CheckSL(SL);			//判断空间是否够用,够用直接将数据放在尾部即可
	SL->data[SL->sz] = x;
	SL->sz++;				//插入之后当前大小+1
}

指定位置插入

  • 只要有插入,就要检查空间是否够用
void SLInsert(SeqList* SL,int pos,SLDataType x)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	assert(pos >= 0 && pos < SL->sz);
    CheckSL(SL);
	int end = SL->sz - 1;
	while (end >=pos-1)			//讲数据从后向后移动,避免被覆盖
	{
		SL->data[end + 1] = SL->data[end];
		end--;
	}
	SL->data[pos-1] = x;
	SL->sz++;			//插入之后当前大小+1
}	

顺序表打印函数

写完插入立马写打印,方便进行调试

void SLprint(SeqList* SL)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	for (int i = 0; i < SL->sz; i++)
	{
		printf("%d ", SL->data[i]);
	}
	printf("\n");
}

查找顺序表数据

int SLFind(SeqList* SL, SLDataType x)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	for (int i = 0; i < SL->sz; i++)
	{
		if (SL->data[i] == x)
		{
			return i;
		}
	}
	return -1;
}

顺序表删除函数

头删

从头部删除数据,删除之后后面的数据依次向前移动一位,要从前往后移动,不然会被覆盖(同头插)

void SLPopFront(SeqList* SL)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	if (SL->sz <= 0)
	{
		printf("表为空,无需删除");
		return;
	}
	int start = 0;
	while (start < SL->sz - 1)
	{
		SL->data[start] = SL->data[start + 1];
		start++;
	}
	SL->sz--;
}

尾删

void SLPopBack(SeqList* SL)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	if (SL->sz <= 0)
	{
		printf("表为空,无需删除");
		return;
	}
	SL->sz--;
}

指定位置删除

后面的数据依次向前移动

void SLEarse(SeqList* SL,int pos)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	assert(pos >= 0 && pos < SL->sz);
	int start = pos-1;
	while (start < SL->sz - 1)
	{
		SL->data[start] = SL->data[start + 1];
		start++;
	}
	SL->sz--;
}

修改顺序表

void SLModify(SeqList* SL, int pos, SLDataType x)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	assert(pos >= 0 && pos < SL->sz);
	SL->data[pos - 1] = x;
}

销毁顺序表

void SLDestroy(SeqList* SL)
{
	assert(SL);	//assert防止传进来的指针为空,进行断言
	free(SL->data);//释放堆空间数据
	SL->data = NULL;//将指针置空预防野指针
	SL->sz = 0;
	SL->capable = 0;
}

文件分类

🌞🌞为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件,模块化管理

test.c

测试文件

#include "SeqList.h"

void test(SeqList* SL)
{
	SLPushBack(SL, 10);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 11);
	SLPushBack(SL, 19);
	SLprint(SL);

	SLPushFront(SL, 12);
	SLPushFront(SL, 13);
	SLPushFront(SL, 14);
	SLprint(SL);

	SLPopBack(SL);
	SLprint(SL);

	SLPopFront(SL);
	SLprint(SL);

	SLInsert(SL, 5, 99);
	SLprint(SL);

	SLModify(SL, 5, 22);
	SLprint(SL);

	//SLEarse(SL, 5);
	//SLprint(SL);

	SLFind(SL,5);
	SLDestroy(SL);

}
int main()
{
	SeqList SL;
	SLInit(&SL);
	test(&SL);
}

SeqList.c

i将所有函数封装在此文件下

#include "SeqList.h"

void SLInit(SeqList* SL)
{
	assert(SL);
	SL->capable = DEFAULT_SZ;
	SL->sz = 0;
	int* ptr = malloc(sizeof(int) * DEFAULT_SZ);
	if (ptr == NULL)
	{
		perror("malloc:");
	}
	SL->data = ptr;
	printf("初始化成功\n");
}

void SLprint(SeqList* SL)
{
	assert(SL);
	for (int i = 0; i < SL->sz; i++)
	{
		printf("%d ", SL->data[i]);
	}
	printf("\n");
}

void CheckSL(SeqList* SL)
{
	assert(SL);
	if (SL->sz == SL->capable)
	{
		int* ptr = NULL;
		ptr = (int*)realloc(SL->data, sizeof(int) * (SL->capable + DEFAULT_INC));
		if (ptr == NULL)
		{
			perror("check:realloc:");
		}
		SL->data = ptr;
		SL->capable += DEFAULT_INC;
		printf("扩容成功\n");
	}
}

void SLPushBack(SeqList* SL,SLDataType x)
{
	assert(SL);
	CheckSL(SL);
	SL->data[SL->sz] = x;
	SL->sz++;
}

void SLPushFront(SeqList* SL, SLDataType x)
{
	assert(SL);
	CheckSL(SL);
	int end = SL->sz - 1;
	while (end >= 0)
	{
		SL->data[end + 1] = SL->data[end];
		end--;
	}
	SL->data[0] = x;
	SL->sz++;
}

void SLPopBack(SeqList* SL)
{
	assert(SL);
	if (SL->sz <= 0)
	{
		printf("表为空,无需删除");
		return;
	}
	SL->sz--;
}

void SLPopFront(SeqList* SL)
{
	assert(SL);
	if (SL->sz <= 0)
	{
		printf("表为空,无需删除");
		return;
	}
	int start = 0;
	while (start < SL->sz - 1)
	{
		SL->data[start] = SL->data[start + 1];
		start++;
	}
	SL->sz--;
}

void SLInsert(SeqList* SL,int pos,SLDataType x)
{
	assert(SL);
	assert(pos >= 0 && pos < SL->sz);
	int end = SL->sz - 1;
	while (end >=pos-1)
	{
		SL->data[end + 1] = SL->data[end];
		end--;
	}
	SL->data[pos-1] = x;
	SL->sz++;
}

void SLEarse(SeqList* SL,int pos)
{
	assert(SL);
	assert(pos >= 0 && pos < SL->sz);
	int start = pos-1;
	while (start < SL->sz - 1)
	{
		SL->data[start] = SL->data[start + 1];
		start++;
	}
	SL->sz--;
}

void SLDestroy(SeqList* SL)
{
	assert(SL);
	free(SL->data);
	SL->data = NULL;
	SL->sz = 0;
	SL->capable = 0;
}

int SLFind(SeqList* SL, SLDataType x)
{
	assert(SL);
	for (int i = 0; i < SL->sz; i++)
	{
		if (SL->data[i] == x)
		{
			return i;
		}
	}
	return -1;
}

void SLModify(SeqList* SL, int pos, SLDataType x)
{
	assert(SL);
	assert(pos >= 0 && pos < SL->sz);
	SL->data[pos - 1] = x;
}

SeqList.h

将主程序所需要的函数全部在头文件中声明,增加代码阅读性

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define SLDataType int
#define DEFAULT_SZ 5
#define DEFAULT_INC 3

typedef struct SeqList
{
	SLDataType* data;
	int sz;
	int capable;
}SeqList;

void SLInit(SeqList* SL);
void SLprint(SeqList* SL);
void SLPushFront(SeqList* SL, SLDataType x);
void SLPushBack(SeqList* SL, SLDataType x);
void SLPopFront(SeqList* SL);
void SLPopBack(SeqList* SL);
void SLInsert(SeqList* SL, int pos, SLDataType x);
void SLEarse(SeqList* SL, int pos);
int SLFind(SeqList* SL, SLDataType x);
void SLModify(SeqList* SL, int pos, SLDataType x);
void SLDestroy(SeqList* SL);

撒花

这就是实现顺序表的全部内容了,创作不易,还请各位小伙伴多多点赞👍关注收藏⭐,以后也会更新各种关于c语言,数据结构的博客,撒花!

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

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

相关文章

webpack5搭建react框架-生产环境配置

webpack5配置react基础生产环境 一、前言 在项目构建时不同的环境下会有不同配置&#xff0c;在前面文章中已经使用webpack5配置好了基础环境和开发环境&#xff0c;但是在生产环境时有些配置和开发环境是不需要的&#xff0c;有些是可以在优化的&#xff0c;所以下面继续生产…

分支和循环语句——1

老铁们&#xff0c;这是博主初识C之后的第一篇C语言学习博客&#xff0c;希望可以给你们带来帮助。 文章目录 一、什么是语句? 二、分支语句 1、if语句 2、switch语句 三、while循环 一、什么是语句? C语句可分为以下五类&#xff1a; 1. 表达式语句 2. 函数调用语句…

模拟不同MIMO-OFDM方案的MATLAB代码(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果​ &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 MIMO技术指在发射端和接收端分别使用多个发射天线和接收天线&#xff0c;使信号通过发射端与接收端的多个天线传送和接收&…

杭州旭航集团,申请纳斯达克IPO上市,募资9800万美元

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;为中国企业提供数字内容营销服务的杭州旭航网络科技有限公司的控股公司Xuhang Holdings Ltd(以下简称&#xff1a;旭航集团)&#xff0c;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提…

随想录Day53--动态规划: 1143.最长公共子序列 ,1035.不相交的线 , 53. 最大子序和

1143.最长公共子序列,这题要画一个二维数组&#xff0c;用两层for循环来遍历每个字符&#xff0c;从而比较是否相等。用dp[i][j]来表示当遍历到text2的第i个字符和text1的第j个字符时&#xff0c;最长的公共子序列为多少。比如说两个字符串&#xff08;“abcde”和“ace”&…

怎么样成为一名Python工程师?到底要会哪些东西?你会了多少?

目录 重点&#xff1a;爬虫部分项目、源码展示python数据分析可视化大屏看板python爬虫爬取淘宝卤鸭货商品数据python游戏开发python自动化办公 重点&#xff1a; 1、做一名程序员&#xff0c;绝对要耐得住寂寞&#xff0c;并且要一直有点兴趣促进你学习。如果你完全没兴趣&am…

electron+vue3全家桶+vite项目搭建【十】vite路径取别名、多环境相关配置

文章目录 引入1.路径取别名配置2.测试别名配置3.环境变量配置4.验证环境变量配置 引入 我们之前写代码的时候用相对路径不是很方便&#xff0c;并且所有环境共用同一套配置也不太好&#xff0c;接下来我们通过vite配置一下路径别名和环境变量 视频讲解 vite官网 demo项目地址…

DIN论文翻译

摘要 在电子商务行业&#xff0c;利用丰富的历史行为数据更好地提取用户兴趣对于构建在线广告系统的点击率(CTR)预测模型至关重要。关于用户行为数据有两个关键观察结果&#xff1a;i) 多样性(diversity)。用户在访问电子商务网站时对不同种类的商品感兴趣。ii) 局部激活(local…

Linux驱动之GPIO函数、IO内存映射、混杂设备驱动

之前学习完了字符设备驱动的大体框架&#xff0c;现在我们就使用这个基本的框架来对硬件进行操作&#xff0c;例如通过指令控制led的状态&#xff0c;编写LED驱动。LED驱动有多种实现方式。 目录 GPIO函数 IO内存映射 混杂设备驱动 GPIO函数 首先加入需要的头文件。 #incl…

欧盟立法者签署公开信,近万人联名“暂停高级AI研发”

来源丨CoinTelegraph 编辑丨liuruiWeb3CN.Pro ChatGPT 曾经的势头有多猛烈如今就被行业大佬抵制的就有多严重。 近日&#xff0c;十几位欧盟 (EU) 政客签署了“暂停高级AI研发”的公开信&#xff0c;呼吁 AI &#xff08;人工智能&#xff09;的“安全”发展&#xff0c;特斯拉…

【Android -- 软技能】聊聊高效开发的一些套路与实践

前言 在开发中&#xff0c;编码我们有分层架构、设计模式做为套路来高效开发&#xff0c;但你也知道编码不是开发的全部&#xff0c;一个完全的开发流程用面向对象思想来概括&#xff0c;它分为OOA&#xff08;面向对象分析&#xff09;、OOD&#xff08;面向对象设计&#xf…

Flutter - 动画使用及自定义动画组件(tabbar跳动动画或文字抖动)

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 Flutter - 动画组件&#xff08;tabbar跳动动画或文字抖动&#xff09; 序效果图动画简介动画类型Flutter动画的一些概念 常用动画实现隐式动画Tween动画Curve动画H…

低代码/无代码平台在软件开发中的应用

随着技术的不断发展&#xff0c;软件开发也在不断地进步。低代码/无代码平台已经成为软件开发的一个新的趋势。在这篇文章中&#xff0c;我们将深入探讨低代码/无代码平台在软件开发中的应用&#xff0c;包括它们的优势、如何选择合适的平台以及如何使用这些平台来开发高质量的…

机器学习 CarRentalData数据集分析和预测

介绍数据集 fuelType&#xff1a;燃料类型 rating&#xff1a;评级 renterTripsTaken&#xff1a;租房者出行 reviewCount&#xff1a;审阅计数 location.city&#xff1a;位置.城市 location.country&#xff1a;地点.国家/地区 location.latitude&#xff1a;位置.纬度 loca…

STM32按键实验中连接按键的GPIO管脚是上拉输入还是下拉输入

一、理解 关于STM32按键实验中连接按键的GPIO管脚是配置为上拉输入还是下拉输入的理解&#xff1a; 以江科大自动协教学视频按键输入实验为例&#xff1a; &#xff08;1&#xff09;按键KEY0<——>PE4 按键另一端接GND &#xff08;2&#xff09;按键KEY1<——&…

入门教学 | 快速了解集简云

集简云是一款超级软件连接器,无需开发,无需代码知识就可以轻松打通数百款软件之间的数据连接,构建自动化与智能化的业务流程。通过自动化业务流程,每月可节省企业数百甚至数万小时的人工成本。 集简云是什么? 集简云是一款超级软件连接器,无需开发,无需代码知识,就可以…

在现成的3D打印机上进行实验理论:一种数据孪生的攻击探测框架

在现成的3D打印机上提供了一种DT中攻击探测框架的DT解决方案的实验演示&#xff0c;作为说明性CPMS资源。通过网络安全DT对打印机正常运行、异常运行和攻击三种情况下的实验数据进行收集和分析&#xff0c;得出攻击检测结果。实验装置概述如下图所示。该实验研究是在现实世界设…

刚刚入职Android开发的应届生,该如何走向架构师

相信有不少从事Android开发的朋友&#xff0c;在工作一两年后会陷入一段迷茫期&#xff0c;有的是在工作中遇到了瓶颈&#xff0c;感觉无法突破&#xff1b;有的是想进阶成为架构师&#xff0c;但不知道如何进阶&#xff0c;因此产生了一些烦恼。为此小编在这里分享Android开发…

安卓开发: Compose 中的 Text 文本控件属性详解

Composable fun Text(text: String,modifier: Modifier Modifier,color: Color Color.Unspecified,fontSize: TextUnit TextUnit.Unspecified,fontStyle: FontStyle? null,fontWeight: FontWeight? null,fontFamily: FontFamily? null,letterSpacing: TextUnit TextU…

wps宏编辑器案例1-自定义函数使用

某公司考情和请假系统是2套独立的系统&#xff0c;人资在月底做考勤统计的时候需要把考勤系统导出的考勤信息表和OA请假流程导出的请假信息表进行合并&#xff0c;得出人员真实的考勤情况。比如员工“忠达”在考勤系统全显示缺勤&#xff0c;实际上请假系统里有4天请假&#xf…