【数据结构】_顺序表

目录

1. 概念与结构

1.1 静态顺序表

1.2 动态顺序表

2. 动态顺序表实现

2.1 SeqList.h

2.2 SeqList.c

2.3 Test_SeqList.c

3. 顺序表性能分析


线性表是n个具有相同特性的数据元素的有限序列。

常见的线性表有:顺序表、链表、栈、队列、字符串等;

线性表在逻辑上是连续的线性结构,在物理结构上并不一定是连续的

线性表在物理上存储时,通常以数组和链式结构的形式存储,分别称之为顺序表和链表。

本文介绍顺序表。

1. 概念与结构

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

要求数据必须从第一个位置开始连续存放;

顺序表在逻辑上是连续的,在物理上也是连续的

1.1 静态顺序表

#define N 100
typedef int SLDataType;
// 静态顺序表
typedef struct SeqList{
	SLDataType arr[N]; // 定长数组
	size_t size;  // 有效数据个数
}SeqList;

在定义时使用定长数组,会造成数组大小若太小则导致不够用,数组若太大则导致空间浪费; 

1.2 动态顺序表

#define N 100
typedef int SLDataType;
// 动态顺序表
typedef struct SeqList {
	SLDataType* arr;
	size_t size;    // 有效数据个数
	size_t capacity;  // 空间大小
}SeqList;

在定义时仅给定数组首元素地址,并且基于size和capacity实现动态增容,相较而言更灵活。

注:1、通常会将顺序表的结构体命名为struct SeqList,即Sequence List;

2、建议目录结构:(注意自定义头文件的包含)

.h头文件:顺序表结构、声明顺序表的方法

.c/.cpp源文件:实现顺序表的方法+测试

3、为便于修改程序,通常会将顺序表结构体中的数据类型进行重命名,可命名为SLDataType;

      为便于编写程序,通常也会对顺序表结构体进行重命名,可重命名为SeqList或SL;

2. 动态顺序表实现

2.1 SeqList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define N 100
typedef int SLDataType;
typedef struct SeqList {
	SLDataType* arr;
	int size;   // 有效数据个数
	int capacity;  // 空间大小
}SL;
// 空间检查
void SLCheckCapacity(SL* psl);
// 打印
void SLPrint(SL* psl);
// 初始化
void SLInit(SL* psl);
// 销毁
void SLDestory(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);
// 查找
int SLFind(SL* psl, SLDataType x);
// 修改
void SLModify(SL* psl, int pos, SLDataType x);

2.2 SeqList.c

#include "SeqList.h"
// 初始化
void SLInit(SL* psl) {
	psl->arr = NULL;
	psl->size = psl->capacity = 0;
}
// 销毁
void SLDestory(SL* psl) {
	if (psl->arr) {
		free(psl->arr);
	}
	psl->arr = NULL;
	psl->size = psl->capacity = 0;
}
// 打印
void SLPrint(SL* psl) {
	assert(psl);
	for (int i = 0; i < psl->size; i++) {
		printf("%d ", psl->arr[i]);
	}
	printf("\n");
}
// 空间检查
void SLCheckCapacity(SL* psl) {
	if (psl->capacity == psl->size) {
		// 常以2倍增容
		int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(psl->arr, newCapacity*sizeof(SLDataType));
		if (tmp == NULL) {
			perror("realloc fail\n");
			exit(1);
		}
		psl->arr = tmp;
		psl->capacity = newCapacity;
	}
}
// 尾插
void SLPushBack(SL* psl, SLDataType x) {
	assert(psl);
	SLCheckCapacity(psl);
	// 写法1
	/*psl->arr[psl->size] = x;
	psl->size++;*/
	// 写法2
	psl->arr[psl->size++] = x;
}
// 头插
void SLPushFront(SL* psl, SLDataType x) {
	assert(psl);
	SLCheckCapacity(psl);
	int count = psl->size;
	// 写法一
	while (count) {
		psl->arr[count] = psl->arr[count-1];
		count--;
	}
	// 写法二
	//for (int i = psl->size; i > 0; i--) {
	//	psl->arr[i] = psl->arr[i - 1];
	//}
	psl->arr[0] = x;
	psl->size++;
}
// 尾删
void SLPopBack(SL* psl) {
	assert(psl);
	assert(psl->size);
	psl->size--;
}
// 头删
void SLPopFront(SL* psl) {
	assert(psl);
	assert(psl->size);
	for (int i = 0; i < psl->size - 1; i++) {
		psl->arr[i] = psl->arr[i+1];
	}
	psl->size--;
}
// 指定位置插入
void SLInsert(SL* psl, int pos, SLDataType x) {
	assert(psl);
	assert(pos>=0 && pos<psl->size);
	SLCheckCapacity(psl);
	for (int i = psl->size; i >psl->size - pos;i--) {
		psl->arr[i] = psl->arr[i-1];
	}
	psl->arr[pos] = x;
	psl->size++;
}
// 指定位置删除
void SLErase(SL* psl, int pos) {
	assert(psl);
	assert(pos >= 0 && pos < psl->size);
	for (int i = pos; i < psl->size - 1; i++) {
		psl->arr[i] = psl->arr[i + 1];
	}
	psl->size--;
}
// 查找
int SLFind(SL* psl, SLDataType x) {
	assert(psl);
	for (int i = 0; i < psl->size; i++) {
		if (psl->arr[i] == x)
			return i;
	}
	return -1;
}
// 修改
void SLModify(SL* psl, int pos, SLDataType x) {
	assert(psl);
	assert(pos >= 0 && pos < psl->size);
	psl->arr[pos] = x;
}

2.3 Test_SeqList.c

#include"SeqList.h"
int main() {
	SL sl1;
	SLInit(&sl1);
	printf("Test SLPushBack:PushBack5~10:\n");
	SLPushBack(&sl1, 5);
	SLPushBack(&sl1, 6);
	SLPushBack(&sl1, 7);
	SLPushBack(&sl1, 8);
	SLPushBack(&sl1, 9);
	SLPushBack(&sl1, 10);
	SLPrint(&sl1);

	printf("TestPushFront:PushFront 4~2:\n");
	SLPushFront(&sl1, 4);
	SLPushFront(&sl1, 3);
	SLPushFront(&sl1, 2);
	SLPrint(&sl1);

	printf("TestPopBack:PopBack 10:\n");
	SLPopBack(&sl1);
	SLPrint(&sl1);

	printf("TestPopFront:PopFront 2:\n");
	SLPopFront(&sl1);
	SLPrint(&sl1);

	printf("TestInsert:Insert arr[4]=99:\n");
	SLInsert(&sl1, 4, 99);
	SLPrint(&sl1);

	printf("TestErase:Erase arr[3]:\n");
	SLErase(&sl1, 3);
	SLPrint(&sl1);

	printf("TestFind: Find 99:\n");
	int retIndex = SLFind(&sl1, 99);
	printf("The index of 99 is: %d\n", retIndex);

	printf("TestModify:Modify 99 to 100:\n");
	SLModify(&sl1, 3, 100);
	SLPrint(&sl1);

	SLDestory(&sl1);
}

测试用例运行结果:

注:1、关于初始化与扩容问题:(方法多样,逻辑完整即可)

上文示例为SLInit使得psl->capacity初值为0,从而在SLCheckCapacity中对于0容量的扩容不能采取一概而论的二倍扩容法,上例使用三目操作符:?使得capacity被赋值为4。

也可在SLInit中就对capacity赋予一个初值,但对应的psl->arr就不可再赋值为NUL了,也需对应malloc相应大小的空间;

2、注意指定位置插入SLInsert与指定位置删除SLErase对pos参数的判定区别:

对于SLInsert,pos可取值size,即实现尾插效果;

对于SLErase,pos不可取值size,arr[psl->size]实际是数组arr最后一个有效数据的下一个位置;

3. 顺序表性能分析

优点:物理空间连续:便于利用下标随机访问

缺点:(1)空间不够需扩容。

① 需要申请新的空间,拷贝数据,释放旧空间,有一定性能消耗;

② 一般增容呈2倍增长,存在空间浪费;

(2)头部或者中间位置的插入删除时涉及数据的移动,时间复杂度为O(N),效率低下

注:越界是不一定报错的,系统对于越界的检查是设岗抽查,以VS为例:

    int a[10];
	a[10] = 1;
	a[11] = 1;

当我们运行如上代码,系统会报错:

再运行下文代码:

    int a[10];
	a[12] = 1;
	a[13] = 1;

系统不会报错。说明系统只重点检查部分位置的越界情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OPencv3.4.1安装及配置教程

来到GitHub上opencv的项目地址 https://github.com/opencv/opencv/releases/tag/3.4.1 以上资源包都是 OpenCV 3.4.1 版本相关资源&#xff0c;它们的区别如下&#xff1a; (1). opencv-3.4.1-android-sdk.zip&#xff1a;适用于 Android 平台的软件开发工具包&#xff08;SDK…

世上本没有路,只有“场”et“Bravo”

楔子&#xff1a;电气本科“工程电磁场”电气研究生课程“高等电磁场分析”和“电磁兼容”自学”天线“、“通信原理”、“射频电路”、“微波理论”等课程 文章目录 前言零、学习历程一、Maxwells equations1.James Clerk Maxwell2.自由空间中传播的电磁波3.边界条件和有限时域…

ZYNQ-IP-AXI-GPIO

AXI GPIO 可以将 PS 端的一个 AXI 4-Lite 接口转化为 GPIO 接口&#xff0c;并且可以被配置为单端口或双端口&#xff0c;每个通道的位宽可以独立配置。 通过使能三态门可以将端口动态地配置为输入或输出。 AXIGPIO 是 ZYNQ PL 端的一个 IP 核&#xff0c;可以将 AXI-Lite Mas…

20.Word:小谢-病毒知识的科普文章❗【38】

目录 题目​ NO1.2.3文档格式 NO4.5 NO6.7目录/图表目录/书目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完&#xff0c;确定之后记得保存最后所有操作完记得再次删除空行 题目 NO1.2.3文档格式 样式的应用 选中应用段落段落→开始→选择→→检查→应用一个一个应用ctr…

为什么应用程序是特定于操作系统的?[计算机原理]

你把WINDOWS程序复制到MAC上使用&#xff0c;会发现无法运行。你可能会说&#xff0c;MAC是arm处理器&#xff0c;而WINDWOS是X86 处理器。但是在2019年&#xff0c;那时候MAC电脑还全是Intel处理器&#xff0c;在同样的X86芯片上&#xff0c;运行MAC和WINDOWS 程序还是无法互相…

LigerUI在MVC模式下的响应原则

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的开发模式&#xff0c;但是也具有其特色的侦听函数&#xff0c;那么当LigerUI作为View层的时候&#xff0c;他所发送后端的必然是表单的数据&#xff0c;在此我们以俩个div为例&#xff1a; {Layout "~/View…

BurpSuite--暴力破解

一.弱口令 1. 基本概念 介绍&#xff1a;弱口令&#xff08;weak password&#xff09;是指那些容易被他人猜测或通过工具破解的密码。虽然弱口令没有严格的定义&#xff0c;但通常它指的是由简单的数字、字母、常用词语或规律性组合构成的密码。 特点&#xff1a; 密码容易被…

深入探讨防抖函数中的 this 上下文

深入剖析防抖函数中的 this 上下文 最近我在研究防抖函数实现的时候&#xff0c;发现一个耗费脑子的问题&#xff0c;出现了令我困惑的问题。接下来&#xff0c;我将通过代码示例&#xff0c;深入探究这些现象背后的原理。 示例代码 function debounce(fn, delay) {let time…

【PostgreSQL内核学习 —— (WindowAgg(一))】

WindowAgg 窗口函数介绍WindowAgg理论层面源码层面WindowObjectData 结构体WindowStatePerFuncData 结构体WindowStatePerAggData 结构体eval_windowaggregates 函数update_frameheadpos 函数 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊…

RocketMQ消息是如何存储的?

大家好&#xff0c;我是锋哥。今天分享关于【RocketMQ消息是如何存储的&#xff1f;】面试题。希望对大家有帮助&#xff1b; RocketMQ消息是如何存储的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 RocketMQ 使用了一个高性能、分布式的消息存储架构…

MongoDB平替数据库对比

背景 项目一直是与实时在线监测相关&#xff0c;特点数据量大&#xff0c;读写操作大&#xff0c;所以选用的是MongoDB。但按趋势来讲&#xff0c;需要有一款国产数据库可替代&#xff0c;实现信创要求。选型对比如下 1. IoTDB 这款是由清华大学主导的开源时序数据库&#x…

电力晶体管(GTR)全控性器件

电力晶体管&#xff08;Giant Transistor&#xff0c;GTR&#xff09;是一种全控性器件&#xff0c;以下是关于它的详细介绍&#xff1a;&#xff08;模电普通晶体管三极管进行对比学习&#xff09; 基本概念 GTR是一种耐高电压、大电流的双极结型晶体管&#xff08;BJT&am…

蓝桥杯python语言基础(4)——基础数据结构(上)

目录 一、列表与元组 &#xff08;一&#xff09;列表 &#xff08;二&#xff09;操作列表 &#xff08;三&#xff09;元组 习题P502 习题P497 二、字符串 &#xff08;一&#xff09;字符串的基本操作 &#xff08;二&#xff09;字符串的常用方法 &#xff08;三&…

langchain基础(三)

Chain&#xff1a; 关于三个invoke&#xff1a; 提示模板、聊天模型和输出解析器都实现了langchain的runnable接口&#xff0c; 都具有invoke方法&#xff08;因为invoke方法是Runnable的通用调用方法&#xff09; 所以可以一次性调用多次invoke直接得到最终结果&#xff1a;…

数据分析和AI丨应对AI实施挑战,工程领域AI应用的五大方法

工程领域的人工智能 &#xff08;AI&#xff09; 已经开始发挥价值&#xff0c;低代码和无代码工具正在使曾经仅属于专业数据科学家的 AI 能力变得大众化。 然而&#xff0c;并非工程领域的每个人都能从中受益&#xff0c;使用新的便捷的 AI 工具提高工作效率并不难&#xff0c…

【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…

games101-(5/6)

光栅化 投影完成之后&#xff0c;视图区域被确定在从[-1,1]的单位矩阵中&#xff0c;下一步就是光栅化 长宽比&#xff1a;ratio 垂直的可视角度&#xff1a;fild-of-view 可以看到的y 轴的范围&#xff0c;角度越小 越接近正交投影 屏幕坐标系 、 将多边形转化成像素 显示…

Linux之详谈——权限管理

目录 小 峰 编 程 ​编辑 一、权限概述 1、什么是权限 2、为什么要设置权限 3、Linux中的权限类别- 4、Linux中文件所有者 1&#xff09;所有者分类&#xff08;谁&#xff09; 2&#xff09;所有者的表示方法 ① u(the user who owns it)&#xff08;属主权限&…

oracle比较一下统计信息差异吧

统计信息发生了哪些变化&#xff1f; 从上次收集到最近一次收集有什么不同&#xff1f; set long 999999 longc 99999 line 100 select report, maxdiffpct from table(dbms_stats.diff_table_stats_in_history(SYS,T1,to_timestamp(2025-01-22 09:01:46,YYYY-MM-DD hh24:mi:s…

【现代深度学习技术】深度学习计算 | 参数管理

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…