详解最基本的数据顺序存储结构:顺序表

新的一年,我觉得这张图很合适!有梦想,敢拼,马上就是除夕了,希望新的一年我们逢考必过,事事顺心,看见朝阳的你是不是嘴角微微上扬!

本篇从0基础白话文讲述顺序表的概念、用法、注意事项、优缺点等等!帮助小白快速掌握!

目录

                      顺序表的概念

                      顺序表的特性

                      顺序表的分类

                      动态顺序表的空间类型设置

         顺序表:开辟与初始化接口

         顺序表:初始化空间

         顺序表:判断空间有效性

         顺序表:扩容空间 

         顺序表:使用空间

         顺序表:对开辟内存的释放

总结

完整代码


顺序表的概念

顺序表是线性表的一种,我们先简单介绍一下线性表:

线性表:最简单、基本、常用的数据结构,由相同特性的数据元素组成的有限序列,除了第一个跟最后一个元素外,其余元素都是收尾相连的,这种连接关系使得线性表在逻辑上呈现线性关系

收尾相连像一根线连接起来的存储方式嘛!下面我们来看看顺序表!

顺序表:在计算机内存中以数组形式保存的线性表,特点就是通过一组地址连续的存储单元依次存储线性表中的各个元素

那它跟数组又有什么区别?

比较形象的说:数组是主零件,顺序表是整个产品,可以实现增删查找等功能!

顺序表的特性

随机访问:通过首地址和元素的序号可以找到指定的元素

存储密度高:每个结点的存储空间只用来存储数据元素,没有额外开销

相邻关系:既然是像一条线把每个存储串联起来,是不是左右元素就有了相邻关系!这使得删除和插入元素比较耗时

顺序表的分类

静态顺序表:可以理解为一个比较抽象的数组,存储大小是提前规定好的。不仅存储大小有限,而且实时面临浪费空间跟空间不够的问题

比如:

这里的n已经写死了,可能需要多次更改宏定义才能更改,这种效率不高!

动态顺序表:相较于动态,我们可以根据需要开辟存储空间,这显得对空间的管理更好!

下面我们主要来学习动态顺序表的实现! 

动态顺序表的空间类型设置

                                                               第一步:分装文件

使用多个文件的原因:一方面显得工程的可读性高

                                    主要还是性能的管理更好

第一步:视图->解决方案管理器->找到需要开辟的文件种类->右键添加->新建项(就可以增加文件个数了!)

一般建议开辟3个文件:2个源文件(.c后缀)(思路大纲+函数实现)

                                      1个头文件(.h后缀)(用来写自实现函数的头文件) 

                                      命名尽量使用英文!

                                                  第二步:实现存储空间的类型

                                                     

                                                 第三步:宏定义常量与结构体变量创建

为了后面可以用宏定义来代替数字,增加可读性,我们设置2个宏常量,对应数字用常量符号代替

如果对宏不清楚的小伙伴,可以看我主页的:程序环境与预处理

创建结构体变量:

接下来会用到动态开辟知识,有不清楚的小伙伴们可以看我主页的:动态内存管理

顺序表:开辟与初始化接口

我们想要动态的存储,肯定要先开辟空间:

首先函数调用:

函数的声明:

 

函数的实现:

 

 顺序表:初始化空间

函数调用:

函数声明:

 

函数实现(注意calloc函数自带初始化功能):

 

顺序表:判断空间有效性

 函数调用(注意传的参数,因为后面还需要调用它,避免麻烦,我们传指针):

函数声明:

 

函数实现:

 

顺序表:扩容空间

 函数调用:

函数声明:

 

函数实现:

 

顺序表:使用空间

 函数调用:

函数声明:

 

函数实现:

 

 顺序表:对开辟内存的释放

我们使用完动态开辟后,需要对空间及时释放,避免内存泄漏!这个知识点可以在我主页:动态内存管理 里面找到!

函数调用:

函数声明:

函数实现:

 

总结

动态顺序表就是利用动态开辟函数来实现,所以我们的基础就是动态内存管理,不会的小伙伴们记得看我主页哦!超级详细的动态详解

完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"text.h"


int main() 
{
	//创建结构体变量
	struct Library s;

	//开辟与初始化
	Open(&s);

	//判断空间有效性
	Judgment(&(s.Pointer));

	//扩容接口
	Expansion(&s);

	//使用空间
	Use(&s);

	//释放空间
	free_t(&s);
}
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 4  //初始最大空间为4
#define ADD 4  //每次扩容增加4个

//单个存储空间类型
typedef struct Information
{
	char name[10];  //名字
	int age;   //年龄
}Information;

//单个空间类型的指针
typedef struct Library
{
	Information* Pointer;   //结构体指针
	int sz;    //sz表示已使用的空间个数
	int max;  //MAX当前表示最大存储量
}Library;

//开辟与初始化
void Open(struct Library* pc);

//判断空间有效性
void Judgment(Information* pc);

//对空间进行扩容
void Expansion(struct Library* pc);

//使用空间
void Use(struct Library* pc);

//释放空间
void free_t(struct Library* pc);
#define _CRT_SECURE_NO_WARNINGS 1
#include"text.h"
#include <cstddef>

//开辟与初始化的实现
void Open(struct Library* pc)
{
	Information* pc = (Information*)calloc(4, sizeof(Information*));
	pc->max = MAX;
	pc->sz = 0;
}

//判断空间有效性
void Judgment(Information* pc)
{
	if (pc == NULL)
	{
		printf("空间开辟失败\n");
		perror("pc");//打印原因
		return;
	}
}

//实现扩容
void Expansion(struct Library* pc)
{
	if (pc->sz == pc->max)
	{
		//表示需要扩容
		Information* str = (Information*)realloc(pc, pc->max + ADD);

		//修改最大存储量
		pc->max += ADD;

		//调用接口进行判断新空间的有效性
		open(&str);

		pc = str;
	}
}

//使用空间
void Use(struct Library* pc)
{
	int input = 0;
	while (input)
	{
		//调用函数接口,判断是否需要扩容
		Expansion(&pc);

		printf("请输入姓名\n");
		scanf("%s", pc->Pointer[pc->sz].name);

		printf("请输入年龄\n");
		scanf("%s", pc->Pointer[pc->sz].age);

		pc->sz++;

		printf("继续输入请按1,退出请按0");
		scanf("%d", &input);
	}
}

//释放空间
void free_t(struct Library* pc)
{
	free(pc->Pointer);
	pc->Pointer = NULL;
	pc -> max = 0;
	pc->sz = 0;
}