C语言_数据结构总结2:动态分配方式的顺序表

news2025/3/9 21:06:18

0——静态分配内存的顺序表和动态分配内存的顺序表的相同之处和不同之处

相同之处
  • 基本操作逻辑相同:无论是静态分配还是动态分配的顺序表,其核心的操作逻辑是一致的。例如插入操作都需要将插入位置之后的元素依次后移,删除操作都需要将删除位置之后的元素依次前移,查找操作也都是通过遍历或者直接定位来完成。

  • 数据元素存储方式相同:两种顺序表都是将数据元素依次存储在连续的内存空间中,都可以通过数组下标来直接访问元素,时间复杂度为 \(O(1)\)。

  • 功能用途相同:都用于实现线性表的功能,支持数据的插入、删除、查找等基本操作。

不同之处
  • 内存分配方式

    • 静态分配:在编译时就确定了顺序表的最大容量,使用数组来存储元素,数组的大小在程序运行过程中不能改变。

    • 动态分配:在程序运行时根据需要动态地分配内存空间,可以通过 mallocrealloc 等函数来调整顺序表的容量。

  • 内存管理

    • 静态分配:不需要手动管理内存,数组的内存空间由系统自动分配和释放。

    • 动态分配:需要手动管理内存,使用 malloc 分配内存,使用 free 释放内存,否则会造成内存泄漏。

  • 表长限制

    • 静态分配:顺序表的最大长度是固定的,一旦达到最大长度就无法再插入新的元素。

    • 动态分配:可以根据需要动态地调整顺序表的容量,理论上只要系统有足够的内存,就可以不断地插入新的元素。

   纯C语言代码,不涉及C++   

代码实现

0. 变量声明

#include<stdio.h>
#include<stdlib.h>

#define InitSize 50  //初始容量
#define Increment 10  //每次扩容的增量
typedef int ElemType;

typedef struct SeqList {
    ElemType* data;  //动态分配数组的指针
    int length;      //顺序表当前的长度(元素个数)
    int capacity;    //顺序表当前容量
}SeqList;

1.初始化

void InitSeqList(SeqList* L) {
	L->data = (ElemType*)malloc(sizeof(ElemType) * InitSize);
	if (L->data == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);  // 退出系统操作
	}
	L->length = 0;
	L->capacity = InitSize;
}

2.扩容

void IncreaseCapacity(SeqList* L) {
	ElemType* newData = (ElemType*)realloc(L->data,(sizeof(ElemType)) * (InitSize + Increment));
	if (newData == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);  // 退出系统操作
	}
	L->data = newData;
	L->capacity += Increment;
}

3.插入

即:在第pos个位置插入value值,即在数组下标pos-1的位置插入value值

int InsertSeqList(SeqList* L,int pos ,ElemType value) {
	//1.判断插入位置是否合法
	if (pos < 1 || pos > L->length + 1)
	{
		printf("插入位置不合法!\n");
		return -1;
	}
	//2.判断顺序表存储空间是否满了
	if (L->length >= L->capacity)
	{
		IncreaseCapacity(L);  //空间不足,进行扩容操作
	}
	//3.将第pos个位置及往后的元素都后移一个位置,空出第pos个位置(这里采用逆序遍历)
	for(int i = L->length; i >= pos; i++)
	{
		L->data[i] = L->data[i - 1];
	}
	//4.插入数据
	L->data[pos - 1] = value;
	//5.表长加1
	L->length++;
	return 0;  //插入成功
}

4.按位查找

即:返回第pos个位置对应的value值

int findValueByPos(SeqList* L, int pos, ElemType* value) {
	//1.判断要查找的位置是否合理
	if (pos < 1 || pos > L->length)
	{
		printf("查找位置不在当前顺序表范围内!\n");
	}
	//2.查找第pos个位置对应的value值
	*value = L->data[pos - 1];
	return 0; //查找成功
}

5.按值查找

即:返回value值对应的位序,即第几个,下标是位序减1

int findPosByValue(SeqList* L, ElemType value) {
	for (int i = 0; i < L->length ; i++)
	{
		if (L->data[i] == value) {
			return i + 1;
		}
	}
	return -1;  //未在该顺序表中找到该值
}

6.删除

即:将第pos个的值赋值交给value变量存储后腾开第pos个位置
     然后将第pos个后的数据都往前移动一个位置,填补第pos个位置

int deleteSeqList(SeqList* L, int pos,ElemType* value) {
	//1. 判断删除位置是否合理,即是否在存有数据的范围内
	if (pos < 1 || pos > L->length)
	{
		printf("待删除位置不在合理范围内!\n");
		return -1; 
	}
	//2. 判断空间是否为空
	if (L->length == 0)
	{
		printf("当前空间未存有数据,无法完成删除操作!\n");
	}
	//3.将要被删除的数据赋值(转存于)value变量
	*value = L->data[pos - 1];

	//4.将第pos个位置往后的元素都往前挪一个位置
	for (int i = pos; i < L->length; i++)
	{
		L->data[i - 1] = L->data[i];
	}
	//5.表长减1
	L->length--;
	return 0; //删除成功
}

7.注销

void destroySeqList(SeqList* L) {
	if (L->data != NULL)
	{
		free(L->data);
		L->data = NULL;
		L->length = 0;
		L->capacity = 0;
	}
}

8.打印

void printSeqList(SeqList* L) {
	if (L->length == 0)
	{
		printf("当前顺序表为空!\n");
	}
	else {
		for (int i = 0; i < L->length ; i++)
		{
			if (i == L->length - 1) {
				printf("%d", L->data[i]);
			}
			else
			{
				printf("%d ", L->data[i]);
			}
		}
		printf("\n");
	}
	printf("--------------------------------------------------\n");
}

9.测试代码

int main() {
	SeqList L;
	InitSeqList(&L);
	//插入数据测试
	if (InsertSeqList(&L,1,18) != 0)
	{
		printf("插入失败!\n");
	}
	if (InsertSeqList(&L,2,7) != 0)
	{
		printf("插入失败!\n");
	}
	if (InsertSeqList(&L,3,34) != 0)
	{
		printf("插入失败!\n");
	}
	printSeqList(&L); // 18 7 34

	//删除数据测试
	ElemType value;
	if (deleteSeqList(&L, 2, &value) != 0)
	{
		printf("删除失败!\n");
	}
	printSeqList(&L); // 18 34

	//按位查找测试,查找第1位的值是什么
	ElemType val;
	if (findValueByPos(&L,1,&val) == 0)
	{
		printf("第1位的数据为:%d\n", val);  //第1位的数据为:18
	}
	else
	{
		printf("查找失败!\n");
	}

	//按值查找测试,查找18在顺序表的第几个位置
	int pos = findPosByValue(&L, 18);
	if (pos != -1)
	{
		printf("值18在顺序表的第%d个位置\n", pos);  //值18在顺序表的第1个位置
	}
	else
	{
		printf("查找失败!\n");
	}

	//测试完记得执行销毁操作,释放空间内存
	destroySeqList(&L);

	return 0;
}

10.完整代码

#include<stdio.h>
#include<stdlib.h>

#define InitSize 50  //初始容量
#define Increment 10  //每次扩容的增量
typedef int ElemType;

typedef struct SeqList {
	ElemType* data;  //动态分配数组的指针
	int length;      //顺序表当前的长度(元素个数)
	int capacity;    //顺序表当前容量
}SeqList;

// 操作1——初始化
void InitSeqList(SeqList* L) {
	L->data = (ElemType*)malloc(sizeof(ElemType) * InitSize);
	if (L->data == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);  // 退出系统操作
	}
	L->length = 0;
	L->capacity = InitSize;
}

// 增加顺序表的容量
void IncreaseCapacity(SeqList* L) {
	ElemType* newData = (ElemType*)realloc(L->data,(sizeof(ElemType)) * (InitSize + Increment));
	if (newData == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);  // 退出系统操作
	}
	L->data = newData;
	L->capacity += Increment;
}

//操作2——插入:在第pos个位置插入value值,即在数组下标pos-1的位置插入value值
int InsertSeqList(SeqList* L,int pos ,ElemType value) {
	//1.判断插入位置是否合法
	if (pos < 1 || pos > L->length + 1)
	{
		printf("插入位置不合法!\n");
		return -1;
	}
	//2.判断顺序表存储空间是否满了
	if (L->length >= L->capacity)
	{
		IncreaseCapacity(L);  //空间不足,进行扩容操作
	}
	//3.将第pos个位置及往后的元素都后移一个位置,空出第pos个位置(这里采用逆序遍历)
	for(int i = L->length; i >= pos; i++)
	{
		L->data[i] = L->data[i - 1];
	}
	//4.插入数据
	L->data[pos - 1] = value;
	//5.表长加1
	L->length++;
	return 0;  //插入成功
}

// 操作3——按位查找,即返回第pos个位置对应的value值
int findValueByPos(SeqList* L, int pos, ElemType* value) {
	//1.判断要查找的位置是否合理
	if (pos < 1 || pos > L->length)
	{
		printf("查找位置不在当前顺序表范围内!\n");
	}
	//2.查找第pos个位置对应的value值
	*value = L->data[pos - 1];
	return 0; //查找成功
}

// 操作4——按值查找,即返回value值对应的位序,即第几个,下标是位序减1
int findPosByValue(SeqList* L, ElemType value) {
	for (int i = 0; i < L->length ; i++)
	{
		if (L->data[i] == value) {
			return i + 1;
		}
	}
	return -1;  //未在该顺序表中找到该值
}

// 操作5——删除:将第pos个的值赋值交给value变量存储后腾开第pos个位置
// 然后将第pos个后的数据都往前移动一个位置,填补第pos个位置
int deleteSeqList(SeqList* L, int pos,ElemType* value) {
	//1. 判断删除位置是否合理,即是否在存有数据的范围内
	if (pos < 1 || pos > L->length)
	{
		printf("待删除位置不在合理范围内!\n");
		return -1; 
	}
	//2. 判断空间是否为空
	if (L->length == 0)
	{
		printf("当前空间未存有数据,无法完成删除操作!\n");
	}
	//3.将要被删除的数据赋值(转存于)value变量
	*value = L->data[pos - 1];

	//4.将第pos个位置往后的元素都往前挪一个位置
	for (int i = pos; i < L->length; i++)
	{
		L->data[i - 1] = L->data[i];
	}
	//5.表长减1
	L->length--;
	return 0; //删除成功
}

// 操作6——注销
void destroySeqList(SeqList* L) {
	if (L->data != NULL)
	{
		free(L->data);
		L->data = NULL;
		L->length = 0;
		L->capacity = 0;
	}
}

//操作7——打印顺序表中存放的数据
void printSeqList(SeqList* L) {
	if (L->length == 0)
	{
		printf("当前顺序表为空!\n");
	}
	else {
		for (int i = 0; i < L->length ; i++)
		{
			if (i == L->length - 1) {
				printf("%d", L->data[i]);
			}
			else
			{
				printf("%d ", L->data[i]);
			}
		}
		printf("\n");
	}
	printf("--------------------------------------------------\n");
}

int main() {
	SeqList L;
	InitSeqList(&L);
	//插入数据测试
	if (InsertSeqList(&L,1,18) != 0)
	{
		printf("插入失败!\n");
	}
	if (InsertSeqList(&L,2,7) != 0)
	{
		printf("插入失败!\n");
	}
	if (InsertSeqList(&L,3,34) != 0)
	{
		printf("插入失败!\n");
	}
	printSeqList(&L); // 18 7 34

	//删除数据测试
	ElemType value;
	if (deleteSeqList(&L, 2, &value) != 0)
	{
		printf("删除失败!\n");
	}
	printSeqList(&L); // 18 34

	//按位查找测试,查找第1位的值是什么
	ElemType val;
	if (findValueByPos(&L,1,&val) == 0)
	{
		printf("第1位的数据为:%d\n", val);  //第1位的数据为:18
	}
	else
	{
		printf("查找失败!\n");
	}

	//按值查找测试,查找18在顺序表的第几个位置
	int pos = findPosByValue(&L, 18);
	if (pos != -1)
	{
		printf("值18在顺序表的第%d个位置\n", pos);  //值18在顺序表的第1个位置
	}
	else
	{
		printf("查找失败!\n");
	}

	//测试完记得执行销毁操作,释放空间内存
	destroySeqList(&L);

	return 0;
}

11.运行截图

如有问题,欢迎指出!

谢谢!

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

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

相关文章

WSL安装及问题

1 概述 Windows Subsystem for Linux&#xff08;简称WSL&#xff09;是一个在Windows 10\11上能够运行原生Linux二进制可执行文件&#xff08;ELF格式&#xff09;的兼容层。它是由微软与Canonical公司合作开发&#xff0c;开发人员可以在 Windows 计算机上同时访问 Windows 和…

基于SpringBoot的商城管理系统(源码+部署教程)

运行环境 数据库&#xff1a;MySql 编译器&#xff1a;Intellij IDEA 前端运行环境&#xff1a;node.js v12.13.0 JAVA版本&#xff1a;JDK 1.8 主要功能 基于Springboot的商城管理系统包含管理端和用户端两个部分&#xff0c;主要功能有&#xff1a; 管理端 首页商品列…

HeidiSQL:一款免费的数据库管理工具

HeidiSQL 是一款免费的图形化数据库管理工具&#xff0c;支持 MySQL、MariaDB、Microsoft SQL、PostgreSQL、SQLite、Interbase 以及 Firebird&#xff0c;目前只能在 Windows 平台使用。 HeidiSQL 的核心功能包括&#xff1a; 免费且开源&#xff0c;所有功能都可以直接使用。…

Ae 效果详解:VR 色差

Ae菜单&#xff1a;效果/沉浸式视频/VR 色差 Immersive Video/VR Chromatic Aberrations VR 色差 VR Chromatic Aberrations效果用于模拟镜头色散现象&#xff0c;在 VR 视频中制造 RGB 通道错位的色彩偏移&#xff0c;以增强视觉风格或创造数字失真效果。 本效果适用于所有色深…

计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【Linux内核系列】:深入解析输出以及输入重定向

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz ★★★ 本文前置知识&#xff1a; 文件系统以及文件系统调用接口 用c语言简单实现一个shell外壳程序 内容回顾 那么在此前的学习中&#xff0c;我们对于Linux的文件系统已经有了…

PyTorch系列教程:Tensor.view() 方法详解

这篇简明扼要的文章是关于PyTorch中的tensor.view()方法的介绍与应用&#xff0c;与reshape()方法的区别&#xff0c;同时给出示例进行详细解释。 Tensor基础 Tensor(张量)的视图是一个新的Tensor&#xff0c;它与原始Tensor共享相同的底层数据&#xff0c;但具有不同的形状或…

软件测试的基础入门(二)

文章目录 一、软件&#xff08;开发&#xff09;的生命周期什么是生命周期软件&#xff08;开发&#xff09;的生命周期需求分析计划设计编码测试运行维护 二、常见的开发模型瀑布模型流程优点缺点适应的场景 螺旋模型流程优点缺点适应的场景 增量模型和迭代模型流程适应的场景…

地下变电站如何实现安全智能运营-以110kV站为例看环境监测与设备联控

1、地下变电站简介 在经济发达的地区&#xff0c;由于城市中心土地资源紧张、征地拆迁费用昂贵&#xff0c;因此采用地下变电站来解决这些问题不失为一个好的途径和思路。地下变电站一般采用室内全封闭式组合电气设备&#xff0c;&#xff12;&#xff12;&#xff10;&#x…

windows无界面后台定时任务 (重启自启动,ODBS为例)

一、前言 mdb(Microsoft Database)是Microsoft Access中使用的一种数据存储格式,可以通过ODBC驱动程序进行访问和操作,在Python中也可以安装相应模块打开。 这是我在项目中更新bs数据的一个实践记录,结合windows定时一起记录一下,方便以后照搬~ 二、安装 Python安装库…

FPGA 实验报告:四位全加器与三八译码器仿真实现

目录 安装Quartus软件 四位全加器 全加器、半加器 半加器&#xff1a; 全加器&#xff1a; 四位全加器电路图 创建项目 半加器 全加器 四位全加器 代码实现 半加器 全加器 四位全加器 三八译码器 创建项目 代码展示 modelsim仿真波形图 四位全加器 三八译码…

win11 Visual Studio 17 2022源码编译 opencv4.11.0 + cuda12.6.3 启用GPU加速

win11 Visual Studio 17 2022 源码编译 opencv4.11.0 cuda12.6.3 启用GPU加速 配置: 生成 opencv 生成 opencv-python 1 下载源码和安装软件 win11 x64 系统 安装Visual Studio 17 2022 下载opencv4.11.0 源码 https://github.com/opencv/opencv/releases/tag/4.11.0 下载…

Ribbon实现原理

文章目录 概要什么是Ribbon客户端负载均衡 RestTemplate核心方法GET 请求getForEntitygetForObject POST 请求postForEntitypostForObjectpostForLocation PUT请求DELETE请求 源码分析类图关系 与Eureka结合重试机制 概要 什么是Ribbon Spring Cloud Ribbon是一个基于HTTP和T…

MuMu-LLaMA:通过大型语言模型进行多模态音乐理解和生成(Python代码实现+论文)

MuMu-LLaMA 模型是一种音乐理解和生成模型&#xff0c;能够进行音乐问答以及从文本、图像、视频和音频生成音乐&#xff0c;以及音乐编辑。该模型利用了用于音乐理解的 MERT、用于图像理解的 ViT 和用于视频理解的 ViViT 等编码器&#xff0c;以及作为音乐生成模型&#xff08;…

2025最新比较使用的ai工具都有哪些,分别主要用于哪些方面?

文章目录 一、AI对话与交互工具二、AI写作与内容生成工具三、AI绘画与设计工具四、AI视频生成工具五、办公与效率工具六、其他实用工具选择建议 根据2025年最新行业动态和用户反馈&#xff0c;以下AI工具在多个领域表现突出&#xff0c;覆盖对话、写作、设计、视频生成等场景&a…

在ArcMap中通过Python编写自定义工具(Python Toolbox)实现点转线工具

文章目录 一、需求二、实现过程2.1、创建Python工具箱&#xff08;.pyt&#xff09;2.2、使用catalog测试代码2.3、在ArcMap中使用工具 三、测试 一、需求 通过插件的形式将点转线功能嵌入ArcMap界面&#xff0c;如何从零开始创建一个插件&#xff0c;包括按钮的添加、工具的实…

后智能体时代的LLM和Agent

文章目录 1. 关于AI重塑的哲学体系2. 关于AI大模型体系的认知3. 关于AI大模型体系的畅想4. 关于人和AI大模型体系的共处5. 写在最后 随着OpenAI、Deepseek、Manus等等智能体的爆火&#xff0c;人们茶前饭后、插科打诨的话题都离不开这些智能体&#xff0c;现状也正如《人民日报…

景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石

在人工智能技术席卷全球的浪潮中&#xff0c;高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商&#xff0c;景联文科技深耕数据标注领域多年&#xff0c;以技术为基、以专业为本&#xff0c;致力于为全球客户提供全场景、高精度、多模态的数…

嵌入式L6计算机网络

Telnet不加密 socket是应用层和下面的内核

华为鸿蒙系统全景解读:从内核设计到生态落地的技术革命

华为鸿蒙系统全景解读&#xff1a;从内核设计到生态落地的技术革命 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 华为鸿蒙系统全景解读&#x…