【C/C++】静态顺序表详解(附完整源码)

news2024/11/24 2:40:33

本章内容

1.什么是线性表

2.什么是顺序表 

3.静态顺序表结构的定义

4.静态顺序表的函数接口实现

5.静态顺序表的问题及思考


1.什么是线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

2.什么是顺序表 

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

顺序表一般可以分为:

1.静态顺序表:使用定长数组存储元素。

2.动态顺序表:使用动态开辟的数组存储元素。

3.静态顺序表结构的定义

#define N 100
typedef int SLDataType;

//静态顺序表
typedef struct SeqList
{
	SLDataType a[N];//定长数组
	int size;//记录存储多少个有效数据
}SeqList;

4.静态顺序表的函数接口实现

//初始化顺序表
void SLInit(SeqList* ps);
//静态顺序表的尾插
void SLPushBack(SeqList* ps,SLDataType data);
//静态顺序表的尾删
void SLPopBack(SeqList* ps);
//静态顺序表的头插
void SLPushFront(SeqList* ps,SLDataType data);
//静态顺序表的头删
void SLPopFront(SeqList* ps);
//pos位置插入数据
void SLInsert(SeqList* ps, int pos, SLDataType data);
//pos位置插入数据
void SLErase(SeqList* ps,int pos);
//查找数据
int SLFind(SeqList* ps, SLDataType data, int begin);
//判断数组是否已满
bool IsFull(SeqList* ps);
//打印存储的数据
void SLPrint(SeqList* ps);

以下是函数接口的实现:

void SLInit(SeqList* ps)
{
	assert(ps);
	ps->size = 0;
}
bool IsFull(SeqList* ps)
{
	assert(ps);
	if (ps->size == N)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void SLPushBack(SeqList* ps,SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//插入数据
	ps->a[ps->size] = data;
	ps->size++;
}
void SLPopBack(SeqList* ps)
{
	assert(ps);
	ps->size--;
}
void SLPushFront(SeqList* ps, SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//挪动数据
	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	//插入数据
	ps->a[0] = data;
	ps->size++;
}
void SLPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	//挪动数据
	for (int i = 0; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}
void SLInsert(SeqList* ps, int pos, SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//挪动数据
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	//插入数据
	ps->a[pos] = data;
	ps->size++;
}
void SLErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size > 0);
	//挪动数据
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}
int SLFind(SeqList* ps, SLDataType data, int begin)
{
	assert(ps);
	assert(begin < ps->size);
	for (int i = begin; i < ps->size; i++)
	{
		if (ps->a[i] == data)
		{
			return i;
		}
	}
	return -1;
}
void SLPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

5.静态顺序表的问题及思考

1.静态顺序表的局限性

静态顺序表只适用于确定知道需要存多少数据的场景。如果数据量未知,N的值太大,造成空间浪费;N的值太小,数据存储不下。

2.接口函数的参数为什么要用结构体指针?

因为尾插、尾删与初始化需要改变结构的内容,若不用结构体指针,形参的改变无法影响实参,则导致无法完成任务;剩下的两个是为了统一与美观。

3.顺序表增删查改的时间复杂度

①顺序表的优势

顺序表的优势是尾插与尾删,为什么呢?

顺序表底层逻辑结构与数组相同,都是在内存上取一连串连续的空间来存储数据。既然这些空间是连续的,那么就意味着我们只需要记住这一连串空间的起始位置,若需要访问与起始位置只相差距离为5的位置时,我们只要在起始位置的地址上加5就可以一步到位。

尾插与尾删最重要的一步就是如何找到尾巴。然而数组几乎可以一步做到这一点,我们知道数组的起始位置,而且用size记录着数组有效长度,那么找尾可以说是及其简单,一步到位。

所以顺序表的尾插与尾删时间复杂度为O(1)。

②顺序表的劣势

与尾插尾删相比,顺序表最大的劣势就是头插与头删。

数组的空间开辟好之后,数组的起始位置已经固定了。我们不能想着将起始位置往前挪一格,然后留出来一个空位置进行插入;同样的也不能将起始位置往后挪一个就完成头删。

正确的头插与头删:

头插:从索引为0的位置开始,将所有数据向后平移一格,然后插入数据。

头删:从索引为1的位置开始,将所有数据向前平移一格,此时索引为0的位置的数据被索引为1的位置的数据覆盖掉了。

头插与头删关键的步骤是平移数据,因此头插与头删的时间复杂度为O(N)。

有关于数组更多详细的讲解,请参考这篇文章:

数据结构为何重要(数组)icon-default.png?t=MBR7http://t.csdn.cn/NB1Uw


6.完整源码

SeqList.h文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#define N 5
typedef int SLDataType;

//静态顺序表
typedef struct SeqList
{
	SLDataType a[N];//定长数组
	int size;//记录存储多少个有效数据
}SeqList;

//初始化顺序表
void SLInit(SeqList* ps);
//静态顺序表的尾插
void SLPushBack(SeqList* ps,SLDataType data);
//静态顺序表的尾删
void SLPopBack(SeqList* ps);
//静态顺序表的头插
void SLPushFront(SeqList* ps,SLDataType data);
//静态顺序表的头删
void SLPopFront(SeqList* ps);
//pos位置插入数据
void SLInsert(SeqList* ps, int pos, SLDataType data);
//pos位置插入数据
void SLErase(SeqList* ps,int pos);
//查找数据
int SLFind(SeqList* ps, SLDataType data, int begin);
//判断数组是否已满
bool IsFull(SeqList* ps);
//打印存储的数据
void SLPrint(SeqList* ps);

SeqList.c文件

#define _CRT_SECURE_NO_DEPRECATE 1
#include"SeqList.h"

void SLInit(SeqList* ps)
{
	assert(ps);
	ps->size = 0;
}

void SLPushBack(SeqList* ps,SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//插入数据
	ps->a[ps->size] = data;
	ps->size++;
}

void SLPopBack(SeqList* ps)
{
	assert(ps);
	ps->size--;
}

void SLPushFront(SeqList* ps, SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//挪动数据
	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	//插入数据
	ps->a[0] = data;
	ps->size++;
}

void SLPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	//挪动数据
	for (int i = 0; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

void SLInsert(SeqList* ps, int pos, SLDataType data)
{
	assert(ps);
	assert(!IsFull(ps));
	//挪动数据
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	//插入数据
	ps->a[pos] = data;
	ps->size++;
}

void SLErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size > 0);
	//挪动数据
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

int SLFind(SeqList* ps, SLDataType data, int begin)
{
	assert(ps);
	assert(begin < ps->size);
	for (int i = begin; i < ps->size; i++)
	{
		if (ps->a[i] == data)
		{
			return i;
		}
	}
	return -1;
}

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

bool IsFull(SeqList* ps)
{
	assert(ps);
	if (ps->size == N)
	{
		return true;
	}
	else
	{
		return false;
	}
}

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

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

相关文章

开源飞控初探(四)ArduPilot::Copter固件源码分析

2022.5.7&#xff0c;基于v4.0.5的分析。官网文档没及时更新&#xff0c;本文对当前版本源码的描述可能和官网不一样。1、无人机全栈分层结构图2、Flight Code固件部分上图中的Flight Code层&#xff0c;分为5个部分&#xff1a;车机层。一份代码通过编译配置&#xff0c;可以支…

行转列,动态列枚举分组

【问题】Hi All,Thanks for the wonderful support the community gets from this forum.I am trying to accomplish this in MongoDB. Didn’t think it could get this complicated. thought the problem was interesting to solve.I am trying to get a count of students b…

【库函数】-还在为操作字符串而烦恼,一篇带你解决这样的烦恼,这里详细介绍关于字符串操作的各个库函数,以及模拟实现

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f389;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a5;作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; 字符函数和字符串函数&#x1f4a6;前言&…

python函数定义中的/和*的作用

python函数定义中的/和*的作用 特殊参数https://docs.python.org/zh-cn/3/tutorial/controlflow.html#special-parameters 函数定义中的单独出现的/和*的作用 / 和 * 是可选的。 /用来指明他前面的函数形参必须使用位置参数。 *用来指明他后面的函数形参必须为关键字参数的…

儿童感染新冠后怎么用药?什么情况需要就医?

儿童感染新冠病毒的症状&#xff0c;病程有哪些特点&#xff1f;退烧药怎么选&#xff0c;怎么吃&#xff1f;孩子有什么症状需要立即就医&#xff1f;...01儿童感染新冠病毒的症状&#xff0c;病程有哪些特点&#xff1f;王泉&#xff1a;儿童是新冠病毒的易感人群。新冠病毒感…

Unity C#热更新框架ILRuntime接入

简介 ILRuntime项目为基于C#的平台&#xff08;例如Unity&#xff09;提供了一个纯C#实现&#xff0c;快速、方便且可靠的IL运行时&#xff0c;使得能够在不支持JIT的硬件环境&#xff08;如iOS&#xff09;能够实现代码的热更新 官方教程 https://ourpalm.github.io/ILRunt…

揭开 TLS 握手的神秘面纱:它是什么以及它是如何工作的

传输层安全性 (TLS) 旨在为网络通信增加安全性。 就是浏览互联网时HTTP和HTTPS的区别。 使用 TLS 为客户端和服务器增加了额外的工作&#xff0c;但它有其好处&#xff0c;包括&#xff1a; 机密性&#xff1a;TLS 将流量包装在加密隧道中。 这使得窃听者不可能在到达目的地的…

[Swift]UIView抖动动画

以拨打视频电话时的拨打按钮抖动为例 import UIKitclass PACallPrepareAlertView: UIView {IBOutlet weak var callIV: UIImageView!private var isLeave: Bool falsedeinit {isLeave true}override func awakeFromNib() {super.awakeFromNib()shakeAction()}private func s…

套接字编程之接口

套接字编程之接口学习套接字之前你需要知道的套接字编程套接字TCP协议和UDP协议区别UDP协议的编写UDP通信两端流程具体操作接口介绍创建套接字为套接字绑定地址信息发送数据接收数据关闭套接字字节序相关接口&#x1f4cc;————本章重点————&#x1f4cc; &#x1f517;…

【Ansible】ansible 变量

ansible 变量 文章目录ansible 变量一、Ansible 变量介绍二、变量命名规则三、变量类型1.全局变量2.剧本变量3.资产变量4.Facts 变量5.注册变量6.变量优先级一、Ansible 变量介绍 在 PlayBook 一节中&#xff0c;将 PlayBook 类比成了 linux 中的shell。那么它作为一门 ansibl…

搜索引擎收录查询,是什么影响了网站被搜索引擎收录

搜索引擎收录是指程序通过辨别把网站内容进行收录&#xff0c;同时会对这些内容进行价值以及其他方面的辨别。 我们想要知道网站有没有被搜索引擎收录&#xff0c;可以借助iis7seo批量查来查询网站有没有被搜索引擎收录。打开iis7seo批量查&#xff0c;添加需要查询的网站网址&…

计算结构体,位段,联合体(共用体)的大小

目录 一、计算结构体的大小 1.1 结构体的计算并不是简单的类型加运算 1.2 内存对齐 1.2.1 内存对齐规则 1.2.2 图解内存对齐 二、计算位段的大小 2.1位段是什么 2.2 位段的内存分配 三、计算联合体的大小 3.1 什么是联合体 3.2 联合体的内存分配 END. 一、计算结构…

Consensus Algorithm -- Raft

The Raft Consensus Algorithm Go 实现&#xff1a;etcd/raft、dragonboat Rust 实现&#xff1a;TiKV C 实现 &#xff1a;nebula-graph-storage、 RethinkDB、logcabin 拜占庭将军问题 拜占庭将军问题&#xff08;Byzantine failures&#xff09;&#xff0c;是由莱斯利兰…

绝绝子!这些技巧真方便

技巧一&#xff1a;快速切换窗口 如果你还在使用桌面底部“任务栏”切换软件窗口&#xff0c;不妨试试这个“快速切换窗口”快捷键&#xff0c;仅需按住【Alt】键不放&#xff0c;并连续点按【tab】键即可实现窗口的快速切换&#xff0c;果真只有亲自上手体验才知道有多香&…

NLP中的对话机器人——问答机器人的应用场景

引言 本文是七月在线《NLP中的对话机器人》的视频笔记&#xff0c;主要介绍FAQ问答型聊天机器人的实现。 讲得还不错&#xff0c;关键是只要1分钱 FAQ问答机器人 FAQ就是一些常见问题与回答&#xff0c;比如https://letsencrypt.org/docs/faq/。 但是我们要做的不是一问一答…

原生RedHat OpenStack搭建

文章目录OpenStack的搭建方式实验软件及镜像实验环境配置NTP节点初始化配置配置本地yum仓库上传镜像文件至NTP节点搭建基于http的网络yum源搭建NTP服务配置Controller控制节点和Compute计算节点初始化配置安装RedHat OpenStack安装部署OpenStack配置OVS桥接OpenStack的搭建方式…

大赛启幕:2023数字中国创新大赛启动发布会在福州召开

2023年1月10日&#xff0c;由数字中国建设峰会组委会主办&#xff0c;福建省数字办、福建省工信厅、福建省通信管理局、福州市政府、泉州市政府、三明市政府、龙岩市政府等共同承办的2023数字中国创新大赛在福建省福州市盛大启幕。 十二届全国政协副主席王钦敏发来书面致辞。中…

Windows 10随机性死机怎么办?

在诸多的电脑问题中&#xff0c;死机算是格外恼人。尤其是当你正在编辑文档&#xff0c;正在做图&#xff0c;正在玩游戏&#xff0c;电脑突然死机&#xff0c;万一再加上没保存…… 如果你在使用Win10系统的过程中遇到随机性死机的问题&#xff0c;赶紧看看这篇文章。 小编整…

LeetCode 113. 路径总和 II

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 113. 路径总和 II&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCode …

简单通讯录的实现

这次我们来实现一个简单的通讯录 目录 1.基本框架及的实现 2.相关结构体的实现 3.通讯录的初始化 4.新建联系人 5.显示所有联系人信息 6.删除联系人 7.查找指定联系人 8.修改联系人信息 9.对联系人进行排序 10.完整代码 既然是通讯录&#xff0c;我们要实现以下内容 …