数据结构入门——顺序表(保姆级教程,增,删,改,查)

news2024/12/25 12:42:27

1.什么是顺序表

1.顺序表可动态增长的数组,要求数据是连续存储的

2.顺序表的定义:

静态顺序表:使用定长数组存储元素(缺点:小了不够用,大了还浪费)

动态顺序表:可根据我们的需要分配空间大小

2.顺序表的接口实现

 3.SeqList.h 头文件:

#pragma once

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

typedef int SLDatatype;
typedef struct SeqList
{
	SLDatatype* a;//指向动态开辟的数组
	int size;  //储存有效数据的个数
	int capacity;//容量
}SL;

void SLInit(SL* psl);//初始化顺序表
void SLDertroy(SL* psl);//销毁顺序表
void SLPrint(SL* psl);//打印顺序表


void SLPushBack(SL* psl, SLDatatype x);//尾插
void SLPushFront(SL* psl, SLDatatype x);//头插
void SLPopBack(SL* psl);//尾删
void SLPopFront(SL* psl);//头删


void SLInsert(SL* psl, int pos, SLDatatype x);//指定下标插入
void SLErase(SL* psl, int pos);//指定下标删除

// 找到返回下标,没有找到返回-1
int SLFind(SL* psl, SLDatatype x);//查找指定值
void SLModify(SL* psl, int pos, SLDatatype x);//修改指定下标数据

SeqList.c 各个接口函数的使用:

1.初始化顺序表

加上断言,防止传进来的指针为空

capacity是使它空间容量变为4

size是有效数据个数置为0

void SLInit(SL* psl)
{
	assert(psl);
	psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);
	if (psl->a == NULL)
	{
		perror("malloc fail");
		return;
	}

	psl->size = 0;
	psl->capacity = 4;
}

2.销毁数组

防止内存泄漏一定要释放内存

void SLDestroy(SL* psl)
{
	assert(psl);
	free(psl->a);
	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

3.打印数组

这里就没有什么说的

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

4.检查顺序表容量是否满了,好进行增容

这里我们要注意,我们在扩容时不用去一个一个扩容,太费劲了,我们可以直接可以扩容2倍,这样既不会太大而产生浪费,也不会太小而不够

void SLCheckCapacity(SL* psl)
{
	assert(psl);

	if (psl->size == psl->capacity)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * psl->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		psl->a = tmp;
		psl->capacity *= 2;
	}
}

5.尾插

void SLPushBack(SL* psl, SLDatatype x)
{
	assert(psl);
    SLCheckCapacity(psl)

	psl->a[psl->size] = x;
	psl->size++;

	//psl->a[psl->size++] = x;(上面写法和下面写法都可以)
}

6.头插

这里我们要注意一下,end = psl -> size - 1,这里我们要说明一下,画图解决问题,我们现在size的位置是最后一个数据的下一位,所以我们要减1

void SLPushFront(SL* psl, SLDatatype x)
{
	assert(psl);
	SLCheckCapacity(psl);//检查容量是否充足

	// 挪动数据
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];//让每个数据都向前移动一位
		--end;
	}

	psl->a[0] = x;//将数据插入头部
	psl->size++;//记录有效数据

}

7.尾删

这里我们会发现有两种检查方法:我个人最喜欢的是暴力检查方法(这里不用过多的说明)

温柔检查方法:不知道 SLDataType 是什么类型的数据,不能冒然的将顺序表最后一个数据赋值为 0,我们只需将有效数据个数 size 减 1 即可达到尾删的目的

void SLPopBack(SL* psl)
{
	assert(psl);
	 //暴力检查
	assert(psl->size > 0);

	// 温柔的检查
	//if (psl->size == 0)
	//	return;

	//psl->a[psl->size - 1] = 0;
	//psl->size--;

	
}

8.头删

这里面有两个方法都一样,只是数组的下角标不同,整体思想就是让后面的数据往前移动一位,size别忘了减1

void SLPopFront(SL* psl)
{
	assert(psl);
	// 暴力检查
	assert(psl->size > 0);

	int start = 0;
	while (start < psl->size-1)
	{
		psl->a[start] = psl->a[start + 1];
		start++;
	}

	//int start = 1;
	//while (start < psl->size)
	//{
	//	psl->a[start-1] = psl->a[start];
	//	start++;
	//}

	psl->size--;


}

9.指定下标插入

这里前面就不用过多说明了,我们在执行循环语句的时候,要想数据插入到数组中,我们需要把要插入数据后面的数据依次向后面移动,给你要插入数据的位置留出来(我们在写完这个代码的时候可以更改前面的头插,和尾插)

void SLInsert(SL* psl, int pos, SLDatatype x)
{
	assert(psl);
	//assert(0 <= pos <= psl->size);
	assert(0 <= pos && pos <= psl->size);

	SLCheckCapacity(psl);

	int end = psl->size - 1;
	while (end >= pos)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}

	psl->a[pos] = x;
	psl->size++;
}

10.指定下标删除

思想和上面——下标插入,的思想一样,无非就是把数据往前移动一位呗(这里也可以更改前面头删和尾删)

void SLErase(SL* psl, int pos)
{
	assert(psl);
	assert(0 <= pos && pos < psl->size);
	//assert(psl->size > 0);

	int start = pos + 1;
	while (start < psl->size)
	{
		psl->a[start - 1] = psl->a[start];
		++start;
	}

	psl->size--;
}

11.查找指定值

int SLFind(SL* psl, SLDatatype x)
{
	assert(psl);

	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}

12.修改指定下标数据

void SLModify(SL* psl, int pos, SLDatatype x)
{
	assert(psl);

	assert(0 <= pos && pos < psl->size);

	psl->a[pos] = x;
}

这里我们要补充一点:越界不一定报错,系统对越界的检查是一种抽查,

  • 越界读一般是检查不出来的

  • 越界写如果是修改到标志位才会检查出来

(系统在数组末尾后设的有标志位,越界写时,恰好修改到标志位了,就会被检查出来)


以上就是我们今天的文章分享,感谢您的关注和点赞!!!


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

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

相关文章

744. 寻找比目标字母大的最小字母

给你一个字符数组 letters&#xff0c;该数组按非递减顺序排序&#xff0c;以及一个字符 target。letters 里至少有两个不同的字符。 返回 letters 中大于 target 的最小的字符。如果不存在这样的字符&#xff0c;则返回 letters 的第一个字符。 示例 1&#xff1a; 输入: le…

3. VBA术语

在本章中&#xff0c;将介绍常用的Excel VBA术语。这些术语将在很多的模块中使用&#xff0c;因此理解其中的每一个术语都很重要。 3.1 模块 模块是编写代码的区域。如下图中&#xff0c;这是一个新的工作簿&#xff0c;因此没有任何模块。 要插入模块&#xff0c;请导航到插…

Cell--瘤内微生物将开辟新疗法

2023年4月13日&#xff0c;弗雷德哈钦森癌症中心的微生物学家Susan Bullman教授在《Cell》杂志发表了关于肿瘤内微生物群的评论。 微生物群是肿瘤微环境的一个组成部分 在患者的肿瘤内部&#xff0c;恶性细胞处在一个复杂的生态系统中&#xff0c;周围是正常细胞的网络&#xf…

socks5与http代理如何转化?stormproxies怎么解决?

Socks5和HTTP代理之间可以通过一些工具或软件进行转化&#xff0c;具体的方法如下&#xff1a; 使用ProxyCap&#xff1a;ProxyCap是一款常用的代理工具&#xff0c;可以将Socks5代理转化为HTTP代理。在ProxyCap中设置Socks5代理的服务器地址和端口&#xff0c;然后在本地设置H…

Java应用高性能的方法和思路

Java应用高性能的方法和思路 目录概述需求&#xff1a; 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge …

软件测试基础概念

1.软件测试的生命周期 需求分析-》测试计划-》测试设计-》测试开发-》测试执行-》测试评估 需求分析&#xff1a;分析需求是否合理和正确 计划:确定软件由谁测试&#xff1f; 什么时候开始测试&#xff0c;什么时候结束测试 测试那些模块 测试设计和测试开发阶段&#xff1a;…

4.19~20(总结)

项目越到后面&#xff0c;推进越难&#xff0c;已经到了发送消息这里了&#xff0c;这个做完&#xff0c;基本上也就完成得七七八八了&#xff0c;后面只需要优化了&#xff0c;但是现在卡在这里就还是有点难搞。 首先&#xff0c;我的界面已经成这样了。 我的打算是这样可以搜…

C++基础知识-2

本期我们接着来讲C的基础知识&#xff0c;没有看过的朋友可以先看看上一期 (16条消息) C基础知识-----命名空间_KLZUQ的博客-CSDN博客 目录 4.缺省参数 5.函数重载 6.引用 7.内联函数 8.auto关键字&#xff08;C11&#xff09; 9. 基于范围的for循环(C11) 10.指针空值nul…

算法记录 | Day37 贪心算法

738.单调递增的数字 思路&#xff1a; 1.一旦出现strNum[i - 1] > strNum[i]的情况&#xff08;非单调递增&#xff09;&#xff0c;首先想让strNum[i - 1]–&#xff0c;然后strNum[i]给为9&#xff0c;这样这个整数就是89&#xff0c;即小于98的最大的单调递增整数。 2…

初始VUE

目录 什么是vue vue的特点 前置js基础知识 vue2 安装vue devtools 搭建开发环境 Vue对象的el及data写法 el的处理 data的处理 特点 什么是js表达式&#xff0c;js代码&#xff08;语句&#xff09; vue脚手架&#xff08;vue cli&#xff09; 使用说明 具体步骤 …

瑞吉外卖:软件开发基础和项目介绍

文章目录 软件开发基础软件开发流程角色分工软件环境 瑞吉外卖项目介绍项目介绍开发流程技术选型功能架构角色 软件开发基础 软件开发流程 需求分析&#xff1a;产品原型&#xff08;大体结构、页面、功能等&#xff09;和需求规格说明书设计&#xff1a;产品文档、UI界面设计…

计算机组成原理——第五章中央处理器(上)

半生风雨半生伤&#xff0c;半醉半醒半心凉 文章目录 前言5.1 CPU的功能和基本结构5.2 指令周期的数据流5.3.1 单总线结构5.3.2 专用通路结构 前言 之前我们就说过CPU主要包括两个部分&#xff0c;运算器和控制器&#xff0c;运算器主要是实现算数运算.逻辑运算&#xff0c; 运…

python正则表达式与re模块

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 python正则表达式与re模块 正则表达式元字符① . 通配符② ^③ $④ *⑤ ⑥ ?⑦ {}⑧ []⑨ \ 转义符⑩…

python 怎么使用pip进行包管理

包管理工具是用来对一些应用程序的包进行管理的工具&#xff0c;比如nodejs使用npm&#xff0c;yarn来进行包管理&#xff0c;linux使用apt来进行包管理。python包管理工具或许不如他们有名&#xff08;实际上pip的大名比前几位更响亮&#xff09;&#xff0c;但绝对比他们好用…

java超市会员积分管理系统

本课题要求采用B/S结构和主流的jsp技术&#xff0c;以java为开发语言&#xff0c;结合后台数据库mysql&#xff0c;并配合使用了MyEclipse等工具软件&#xff0c;完成超市会员管理系统的设计与后台管理功能开发。 该系统主要功能如下&#xff1a; 会员信息的管理&#xff1a;包…

MySQL数据库:数据库表的设计

一、ER实体关系图 1.概念 百度百科&#xff1a; ER图是用来描述某一组织(单位)的概念模型&#xff0c;提供了表示实体、属性和联系的方法。构成ER图的基本要素是实体、属性和关系。 ER图是用来描述某一组织(单位)的概念模型&#xff0c;提供了表示实体、属性和联系的方法。构…

asp.net房屋租赁管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net房屋租赁管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言 开发 asp.net房屋租赁管理系统VS开发s…

如何搭建用户生命周期模型

如何搭建用户生命周期模型 摘要一、问题背景二、用户生命周期模型1、用户生命周期模型简介2、对用户生命周期认知的几点误区 三、如何搭建并应用用户生命周期模型1、使用场景2、搭建步骤&#xff08;1&#xff09;梳理用户成长路径&#xff08;2&#xff09;寻找驱动用户进入下…

【动力节点】springsecurity课程笔记6-13章

** 6 密码处理 6.1 为什么要加密&#xff1f; csdn 密码泄露事件 泄露事件经过&#xff1a;https://www.williamlong.info/archives/2933.html 泄露数据分析&#xff1a;https://blog.csdn.net/crazyhacking/article/details/10443849 6.2加密方案 密码加密一般使用散列函…

ATTCK v12版本战术实战研究——提权(二)

一、前言 前几期文章中&#xff0c;我们介绍ATT&CK 14项战术中提权战术&#xff08;二&#xff09;&#xff0c;包括提权前7项子技术。那么从前文中介绍的相关提权技术来开展测试&#xff0c;进行更深一步的分析。本文主要内容是介绍攻击者在运用提权技术时&#xff0c;在…