Java数据结构之顺序表详解

 更新时间:2023年07月20日 10:07:53   作者:学习同学  
这篇文章主要介绍了Java数据结构之顺序表详解,线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储,需要的朋友可以参考下

一. 线性表

1.1 定义

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

看这个定义 我们再联想前面的知识

是不是发现数组的使用和这个定义十分相似

没错 其实顺序表本质上就是数组

但是它再数组上增加了一点内容

1.2 特点

它分为静态的和动态的

这个特点是不是又发现和我们上面做的项目通讯录十分相似

它是连续存储的 不能跳过元素

二. 顺序表

2.1 定义

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

2.2 代码

struct SeqList
{
	int a[100]; //数组
	int size; //数组中存储了多少个数字 
};

我们说类似这个结构的 就是一个顺序表

但是呢 为了我们以后改变数字方便 我们可以把这里的100 定义成一个宏 这样我们以后如果想修改顺序

表的大小 只要改变宏就可以了

代码表示如下

// 静态顺序表
#define N 100
struct SeqList
{
	int a[N]; //数组
	int size; //数组中存储了多少个数字 
};

上面就是一个标准的静态数据表 假如说 我们想使用顺序表来管理一个字符串

#define N 100
struct SeqList
{
	char a[N]; //数组
	int size; //数组中存储了多少个数字 
};

我们可以改变int类型 变为char类型的数据 但是这样每次改也太麻烦了 所以我们依旧可以再上面定义

一个宏变量

#define N 100
typedef char SLDateType
struct SeqList
{
	int SLDateType[N]; //数组
	int size; //数组中存储了多少个数字 
};

我们说 就可以使用这样的格式 方便以后一次性改变所有的变量类型

但是呢 这样子我们看整个结构体还是有点麻烦 我们再将这个结构体简化一下

typedef struct SeqList
{
	int SLDateType[N]; //数组
	int size; //数组中存储了多少个数字 
}SL;

这样子就能得到一个相对完美的静态顺序表啦

2.3 功能需求

在创建好这个静态表之后 我们要开始大概创建它的一些功能啦

比如说以下的一些功能

vovoid SeqListInit(SL* ps);
void SeqListPushBack(SL* ps, SLDateType x);
void SeqListPopBack(SL* ps);
void SeqListPushFront(SL* ps, SLDateType x);
void SeqListPopFront(SL* ps);

初始化 尾插 头插等等

2.4 静态顺序表的特点以及缺点

特点: 如果满了就不让插入

缺点: 不知道给多少合适

2.5 动态的顺序表

typedef struct SeqList
{
	SLDateType* a; //数组
	int size; //数组中存储了多少个数字 
	int capacity;
}SL;

是不是跟我们的通讯录特别相似

其实原理本质上都是一样的 这里只是命名更加规范了

2.6 动态顺序表接口的实现

初始化

void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

尾插

在这里插入图片描述

我们先写空间足够的情况

void SeqListPushBack(SL* ps, SLDateType x)
{
	ps->a[ps->size] = x;
	ps->size++;
}

代码表示如上

那么我们接下来我们写上面的两种情况

这里我们要注意的是 一开始我们将指针置空 占用的空间为0

所以说我们一开始至少要开始4个数据的空间 这里可以使用一个三目操作符解决

int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;

养成良好的习惯 代码加注释

void SeqListPushBack(SL* ps, SLDateType x)
{
	// 如果没有空间或者空间不足 我们就扩容 
	// 扩容失败就报错
	if ((ps->size)==(ps->capacity))
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDateType* tmp =(SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));
		if (tmp==NULL)
		{
			perror("pushback realloc");
		}
	}
	ps->a[ps->size] = x;
	ps->size++;
}

这里我们使用一个打印函数看看整个数据的内容

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

打印出结果如下

在这里插入图片描述

在使用完成之后我们还需要一个借口函数来释放我们的动态开辟的内存 从而避免内存泄漏的问题

void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a == NULL;
	ps->capacity = ps->size = 0;
}

接下来我们看尾删函数

void SeqListPopBack(SL* ps)
{
	ps->size--;
}

尾删的话其实我们只要将size-- 就可以

但是这里我们要注意一点 当size为0的时候 这里就不可以再删除了 所以我们还需要完善以下上面的代码

void SeqListPopBack(SL* ps)
{
	if (ps->size==0)
	{
		perror("SeqListPopBack");
	}
	ps->size--;
}

接下来我们看前插

void SeqListPushFront(SL* ps, SLDateType x)
{
	// 考虑扩容问题
	if ((ps->size) == (ps->capacity))
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->capacity = newcapacity;
		SLDateType* tmp = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));
		if (tmp == NULL)
		{
			perror("pushback realloc");
		}
		ps->a = tmp;
	}
	// 头插
	int end = ps->size - 1;
	while (end>=0)
	{
		ps->a[end + 1] = ps->a[end];
	}
	ps->a[0] = x;
	ps->size++;
}

接下来我们来看头删

在这里插入图片描述

这就要求我们定义一个bejin 然后从前往后依次挪数据

代码表示如下

void SeqListPopFront(SL* ps)
{
	int bejin = 0;
	while (bejin<ps->size-1)
	{
		ps->a[bejin] = ps->a[bejin + 1];
		bejin++;
	}
	ps->size--;
}

在这里插入图片描述

这里我们基本实现了顺序表的所有接口函数啦

三. 代码

头文件

#pragma once
#define N 100
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a; //数组
	int size; //数组中存储了多少个数字 
	int capacity;
}SL;
void SeqListInit(SL* ps);
void SeqListDestory(SL* ps);
void SeqListPushBack(SL* ps, SLDateType x);
void SeqListPopBack(SL* ps);
void SeqListPushFront(SL* ps, SLDateType x);
void SeqListPopFront(SL* ps);
void SeqListPrint(SL* ps);
// . 
//...

主文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "seqlist.h"
void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}
void SeqListPrint(SL* ps)
{
	int i = 0;
	for ( i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
void SeqListPushBack(SL* ps, SLDateType x)
{
	// 如果没有空间或者空间不足 我们就扩容 
	// 扩容失败就报错
	if ((ps->size)==(ps->capacity))
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->capacity = newcapacity;
		SLDateType* tmp =(SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));
		if (tmp==NULL)
		{
			perror("pushback realloc");
		}
		ps->a = tmp;
	}
	ps->a[ps->size] = x;
	ps->size++;
}
void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}
void SeqListPopBack(SL* ps)
{
	if (ps->size==0)
	{
		perror("SeqListPopBack");
	}
	ps->size--;
}
void SeqListPushFront(SL* ps, SLDateType x)
{
	// 考虑扩容问题
	if ((ps->size) == (ps->capacity))
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->capacity = newcapacity;
		SLDateType* tmp = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));
		if (tmp == NULL)
		{
			perror("pushback realloc");
		}
		ps->a = tmp;
	}
	// 头插
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}
void SeqListPopFront(SL* ps)
{
	int bejin = 0;
	while (bejin<ps->size-1)
	{
		ps->a[bejin] = ps->a[bejin + 1];
		bejin++;
	}
	ps->size--;
}

测试文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "seqlist.h"
int main()
{
	SL a1;
	SeqListInit(&a1);
	SeqListPushBack(&a1, 1);
	SeqListPushBack(&a1, 2);
	SeqListPushBack(&a1, 3);
	SeqListPushBack(&a1, 4);
	SeqListPushBack(&a1, 5);
	SeqListPrint(&a1);
	SeqListPopBack(&a1);
	SeqListPrint(&a1);
	SeqListPopFront(&a1);
	SeqListPrint(&a1);
	SeqListDestory(&a1);
	return 0;
}

到此这篇关于Java数据结构之顺序表详解的文章就介绍到这了,更多相关Java顺序表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL注入攻击及其在SpringBoot中使用MyBatisPlus的防范策略的方法

    SQL注入攻击及其在SpringBoot中使用MyBatisPlus的防范策略的方法

    本文介绍了如何使用SpringBoot整合JavaDeeplearning4j构建一个文本摘要生成系统,该系统能够自动从长篇文本中提取关键信息,生成简洁的摘要,帮助用户快速了解文本的主要内容,系统使用LSTM神经网络模型进行训练,并通过SpringBoot创建RESTful API进行调用
    2024-11-11
  • 在idea 中添加和删除模块Module操作

    在idea 中添加和删除模块Module操作

    这篇文章主要介绍了在idea 中添加和删除模块Module操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • SpringBoot+Vue.js实现前后端分离的文件上传功能

    SpringBoot+Vue.js实现前后端分离的文件上传功能

    这篇文章主要介绍了SpringBoot+Vue.js实现前后端分离的文件上传功能,需要的朋友可以参考下
    2018-06-06
  • 将SpringBoot项目无缝部署到Tomcat服务器的操作流程

    将SpringBoot项目无缝部署到Tomcat服务器的操作流程

    SpringBoot 是一个用来简化 Spring 应用初始搭建以及开发过程的框架,我们可以通过内置的 Tomcat 容器来轻松地运行我们的应用,本文给大家介绍 SpringBoot 项目部署到独立 Tomcat 服务器的操作流程,需要的朋友可以参考下
    2024-05-05
  • SpringBoot集成tomcat详解实现过程

    SpringBoot集成tomcat详解实现过程

    采用spring boot之后,一切变得如此简单,打包->java-jar->运维,只需要一个jar包便可以随意部署安装。这篇文章,将对 spring boot集成tomcat的源码进行分析,探索其内部的原理
    2023-02-02
  • Java实现随机出题,10道10以内加减法计算代码实例

    Java实现随机出题,10道10以内加减法计算代码实例

    这篇文章主要介绍了Java实现随机出题,10道10以内加减法计算,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • springCloud gateWay 统一鉴权的实现代码

    springCloud gateWay 统一鉴权的实现代码

    这篇文章主要介绍了springCloud gateWay 统一鉴权的实现代码,统一鉴权包括鉴权逻辑和代码实现,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • 浅谈Java中的Filter过滤器

    浅谈Java中的Filter过滤器

    本篇文章主要介绍了浅谈Java中的Filter过滤器,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 你所不知道的Spring的@Autowired实现细节分析

    你所不知道的Spring的@Autowired实现细节分析

    这篇文章主要介绍了你所不知道的Spring的@Autowired实现细节分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java集合List相关面试题整理大全

    Java集合List相关面试题整理大全

    这篇文章主要给大家介绍了关于Java集合List相关面试题整理的相关资料,下面将提供一些常见的Java集合类面试题及其解答,帮助读者更好地准备面试,需要的朋友可以参考下
    2024-01-01

最新评论