数据结构顺序表

news2025/2/11 15:52:56

在这里插入图片描述
今天主要讲解顺序表,实现顺序表的尾插,头插,头删,还有尾删等操作,和我们之前写的通讯录的增删查改有类似的功能。接下来让我们开始我们的学习吧。
1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结
构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物
理上存储时,通常以数组和链式结构的形式存储

在这里插入图片描述
顺序表其实本质上和数组差不多。
2.顺序表
2.1概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组
上完成数据的增删查改。
顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
    静态的顺序表通俗点讲就是死的,我们不能改变里面的元素,一开始是多少就是多少,不能实现我们的增删查改一些操作,所以我们写顺序表的时候基本上都是动态。
    静态顺序表的代码。
    在这里插入图片描述
typedef struct SeqList
{
	int arry[100];
	int size;
}SL

我们可以写成这样,但是如果我存储数据的个数不是100的话又要改,我们可以写成这样,在前面define一下。
在这里插入图片描述
同时我们的顺序表可能不只是int 类型的 这个时候我们就可以typedef一下,下次改的时候就方便很多。
在这里插入图片描述
但是我们说静态的顺序表存在缺陷,这个时候我们就得动态开辟空间,我们可以写一个动态顺序表。

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* arry;//指向顺序表开始位置
	int size;//个数
	int capacity;//空间
}SL;

这样的话我们就可以用动态开辟的方式实现了。

首先我们要初始化顺序表。

在这里插入图片描述
在这里插入图片描述
我们一开始这样写的时候,经过调试可以发现我们的s并没有初始化,在VS2022下直接会提醒你使用未初始化的变量s,这是为什么,是因为我们形参是实参的一份临时拷贝,并不能改变实参,所以我们传值不行,要传地址过去次啊可以解决。
在这里插入图片描述

#include"SeqList.h"
void SLInit(SL* ps)
{
	ps->arry = NULL;
	ps->capacity = ps->size = 0;
}
void SLtest1()
{
	SL s;
	SLInit(&s);
}


int main()
{
	SLtest1();
	return 0;
}

那我们接下来初始化之后实现一个简单的尾插功能吧


void SLPushBack(SL* ps, SLDataType x)
{
	ps->arry[ps->size] = x;
	ps->size++;
}

我们一开始肯定会这样想,在末尾插入数字,那我们就在末尾找到这个位置,然后插入就行,但是这会有问题,一个原因就是如果这个数组满了,我们就不能插入,插入的化就要扩容,而我们一开始为什么要写动态顺序表的原因就是这个,除了这个原因以外,还有一个原因就是如果我们一开始放的是空指针的时候,这个是时候插入就相当于非法访问,所以我们在插入的时候要进行一下判断。那因为后面头插的时候也会遇到这样的问题,我们干脆给它写成一个函数,这样就方便我们使用。
尾插函数

void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arry, sizeof(SLDataType) * NewCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->arry = tmp;
		ps->capacity = NewCapacity;
	}
	
} 

所以我们的尾插也可以写成

void SLPushBack(SL* ps, SLDataType x)
{
	SLCheckCapacity(ps);
	ps->arry[ps->size] = x;
	ps->size++;
}

我们为什么取得是结构体的地址,原因还是形参只是实参的一个临时拷贝,形参改变并不会改变实参

打印顺序表的函数。

void SLPrint(SL* ps)
{

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

打印函数可以传地址也可以传值,因为打印不会改变我们的内容,我们这里写的就是传址。
实现打印函数,我们其实可以在这些前面都加上assert,做好防御,因为如果传进来的是一个空指针的话,这就会,我们是没有办法进行修改的,所以在函数进来的时候都写好断言,从根本上解决问题。

接下来我们就写一个尾删,尾删就更简单了,直接–就行了,但是我们还要考虑一个问题就是里面一开始的时候有没有数字,如果这个顺序表为空就没有必要删除了。

void SLPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;

}

从上面顺序表的尾删和尾插来看,其实顺序表相对来说效率还是比较快的,但是头删和头插的效率并不是特别高,我们继续接着写

头插

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->arry[end + 1] = ps->arry[end];
		end--;
	}
	ps->arry[0] = x;
	ps->size++;

}

头插的时候也要进行检查 否则空间满的话,就会越界。

头删

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	int begin = 0;
	while (begin < ps->size-1)
	{
		ps->arry[begin] = ps->arry[begin + 1];
		begin++;
	}
	ps->size--;
}

为什么要assert(ps->size > 0)是因为如果数都没有的话就不需要删了,所以就需要断言一下。

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

写完这个其实头插就可以改成SLInsert(SL* ps, 0, SLDataType x)尾插就可以改成SLInsert(SL* ps, ps->size-1, SLDataType x)
那我们在实现一个在pos位置进行删除的代码。

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

那这样我们的每个功能基本都实现了,因为我们一开始realloc空间,所以我们现在要销毁原来的空间。

void SLDestory(SL* ps)
{
	if (ps->arry != NULL)
	{
		free(ps->arry);
		ps->arry = NULL;
	}

}

这样我们其实还可以用一个菜单来实现这写功能,和通讯录那个差不多,就设置一个菜单,这里小编就不搞了
给大家分享一下完整代码。

SeqList.h

#pragma once

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

//#define N 100
//typedef int SLDataType;
//typedef struct SeqList
//{
//	int arry[N];
//	int size;
//}SL;

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* arry;//指向顺序表开始位置
	int size;//个数
	int capacity;//空间
}SL;

//初始化
void SLInit(SL* ps);

//尾插
void SLPushBack(SL* ps, SLDataType x);

//检查空间是否够
void SLCheckCapacity(SL* ps);

void SLPrint(SL* ps);

void SLPopBack(SL* ps);

//头插
void SLPushFront(SL* ps, SLDataType x);

//头删
void SLPopFront(SL* ps);

void SLInsert(SL* ps, int pos, SLDataType x);

void SLErase(SL* ps, int pos);


void SLDestory(SL* ps);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"SeqList.h"
void SLInit(SL* ps)
{
	ps->arry = NULL;
	ps->capacity = ps->size = 0;
}

void SLCheckCapacity(SL* ps)
{
	assert(ps != NULL);
	if (ps->capacity == ps->size)
	{
		int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arry, sizeof(SLDataType) * NewCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->arry = tmp;
		ps->capacity = NewCapacity;
	}
	
} 
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps != NULL);
	SLCheckCapacity(ps);
	ps->arry[ps->size] = x;
	ps->size++;
}

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

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	ps->size--;

}

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->arry[end + 1] = ps->arry[end];
		end--;
	}
	ps->arry[0] = x;
	ps->size++;

}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	int begin = 0;
	while (begin < ps->size-1)
	{
		ps->arry[begin] = ps->arry[begin + 1];
		begin++;
	}
	ps->size--;
}



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

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

void SLDestory(SL* ps)
{
	if (ps->arry != NULL)
	{
		free(ps->arry);
		ps->arry = NULL;
	}

}

今天的分享就到这里了,我们下次再见!!!

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

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

相关文章

保证接口数据安全的10种方式

我们日常开发中&#xff0c;如何保证接口数据的安全性呢&#xff1f;个人觉得&#xff0c;接口数据安全的保证过程&#xff0c;主要体现在这几个方面&#xff1a;一个就是数据传输过程中的安全&#xff0c;还有就是数据到达服务端&#xff0c;如何识别数据&#xff0c;最后一点…

安达发|企业如何提高生产实现精细化管理

随着市场竞争的加剧&#xff0c;企业如何提高生产效率和降低成本成为了关键。本文将探讨生产计划排程表的制定方法&#xff0c;帮助企业实现精细化管理&#xff0c;提升竞争力。 在传统的生产管理中&#xff0c;企业往往依赖于人工经验和直觉来制定生产计划&#xff0c;导致生产…

docker复现Nginx配置漏洞

目录 1.docker环境搭建 2.复现过程 2.1CRLF(carriage return/line feed)注入漏洞 2.2.目录穿越 2.3.add_header覆盖 1.docker环境搭建 1.安装docker apt-get update apt-get install docker.ioyum install docker.io 2.下载并解压docker环境Nginx配置漏洞安装包 链接&am…

最强的表格组件—AG Grid使用以及License Key Crack

PS: 想要官方 License Key翻到最后面 Ag Grid简介 Ag-Grid 是一个高级数据网格&#xff0c;适用于JavaScript/TypeScript应用程序&#xff0c;可以使用React、Angular和Vue等流行框架进行集成。它是一种功能强大、灵活且具有高度可定制性的表格解决方案&#xff0c;提供了丰富…

23款奔驰AMG GT50升级原厂HUD抬头显示系统,增加您的行车安全性

HUD是平视显示器的简称&#xff0c;它原先是运用在航空器上的飞行辅助仪器。指飞行员不需要低头&#xff0c;就能够看到他需要的重要资讯。由于HUD的方便性以及能够提高飞行安全&#xff0c;这项技术后来也发展到汽车行业。汽车搭载的HUD抬头数字显示功能&#xff0c;是利用光学…

类的默认成员函数(C++)

类的默认成员函数 1.构造函数特性 2.析构函数特性 3.拷贝构造函数特性 4.赋值重载函数运算符重载赋值运算符重载 const成员函数取地址运算符重载 1.构造函数 构造函数是一个特殊的成员函数&#xff0c;名字与类名相同&#xff0c;创建类类型对象时由编译器自动调用&#xff0c…

怎么制作gif动态图?gif图片在线制作攻略分享

现在许多品牌和营销活动也使用gif动态图来吸引用户注意力、提升品牌形象或传递特定的信息&#xff0c;那么gif制作的过程到底难不难呢&#xff1f;其实只需要使用gif图片在线制作工具就非常简单了&#xff0c;下面以图片制作gif&#xff08;https://www.gif.cn&#xff09;为例…

一个事务插入,另外一个事务更新操作,是否会更新成功?

1.前言 同样另外一个非常有意思的题目&#xff0c;值得我们思考。大概背景是这个样子的。如果有一个事务A进行插入 id > 100, 同时另外一个事务B进行更新update id > 100。那么事务B是否会更新成功。我们来画一个时序图&#xff1a; time事务A事务B备注T1insert id >…

MPAS-A原理及陆面模式的基本概念

跨尺度预测模式&#xff08;The Model for Prediction Across Scales - MPAS&#xff09;是由洛斯阿拉莫斯实验室和美国国家大气研究中心(NCAR)共同开发&#xff0c;其由3个部分组成&#xff0c;分别称为 MPAS-A&#xff08;大气模型&#xff09;、MPAS-O&#xff08;海洋模型&…

Nginx+Tomcat负载均衡、动静分离实例详细部署

一、反向代理两种模式 四层反向代理 基于四层的iptcp/upd端口的代理 他是http块同一级&#xff0c;一般配置在http块上面。 他是需要用到stream模块的&#xff0c;一般四层里面没有自带&#xff0c;需要编译安装一下。并在stream模块里面添加upstream 服务器名称&#xff0c;…

uni-app日期选择器

写个简单的日期选择器&#xff0c;还没搞样式&#xff0c;所以有点丑 大概长这样吧 首先是这个picker选择器&#xff0c;mode选择日期&#xff0c;end是写一个范围前日期&#xff0c;:end就是这个日期是动态变化的&#xff0c;还有change函数 <template><view>&l…

LeetCode150道面试经典题--验证回文串(简单)

1.题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回 true &#xff1b;否…

通过这些case,我把项目LCP时间减少了1.5s

您好&#xff0c;如果喜欢我的文章&#xff0c;可以关注我的公众号「量子前端」&#xff0c;将不定期关注推送前端好文~ 前言 最近在做公司几个项目性能优化&#xff0c;整理出一些比较有用且常见的case来分享一下。 A项目优化 白屏相关 DNS预连接、资源预解析 对于公共域…

还不会python 实现常用的数据编码和对称加密?看这篇文章就够啦~

♥ 前 言 相信很多使用 python 的小伙伴在工作中都遇到过&#xff0c;对数据进行相关编码或加密的需求&#xff0c;今天这篇文章主要给大家介绍对于一些常用的数据编码和数据加密的方式&#xff0c;如何使用 python 去实现。话不多说&#xff0c;接下来直接进入主题&#xf…

install imap error

【错误翻译】 Try to run this command from the system terminal. Make sure that you use the correct version of pip installed for your Python interpreter located at D:\Program Files (x86)\Python\Python39\python.exe. 尝试从系统终端运行此命令。请确保使用安装在…

【UE4 RTS】09-Day and Night

前言 本篇博客实现的效果是太阳和天空会随着游戏时间的变化而变化。 效果 步骤 1. 设置“LightSource”为可移动的 2. 新建一个文件夹&#xff0c;命名为“Lighting” 3. 打开游戏状态“RTS_GameState_BP”&#xff0c;添加一个函数命名为“GetGameSpeed” 添加一个浮点类型…

利用 Splashtop Enterprise 改善公司的网络安全

在我们日益数字化的世界中&#xff0c;对强有力的网络安全措施的需求从未像现在这样迫切。随着组织扩大其数字足迹并采用远程办公解决方案&#xff0c;他们面临着一系列不断变化的挑战。 威胁行为者不断寻找利用漏洞的新方法&#xff0c;这使得企业保持领先地位至关重要。俗话…

【Cartopy】库的安装和瓦片加载(天地图、高德等)

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 Cartopy基础入门 【Cartopy】库的安装和天地图瓦片加载 【Cartopy】【Cartopy】如何更好的确定边界显示 【Cartopy】【Cartopy】如何丝滑的加载Geojso…

搜狗输入法曝加密系统漏洞(已修复),黑客可窃取用户输入的内容

近期&#xff0c;来自加拿大多伦多大学公民实验室的研究人员在国内热门输入法——搜狗输入法的加密系统中发现了漏洞&#xff0c;能允许网络监听者破译用户的输入内容。目前该漏洞已得到修复。 研究人员发现漏洞的软件版本涉及三大主流系统&#xff0c;分别是Windows 13.4版本、…