数据结构 顺序表1

news2025/1/16 2:58:49

1. 何为顺序表:

        顺序表是一种线性数据结构,是由一组地址连续的存储单元依次存储数据元素的结构,通常采用数组来实现。顺序表的特点是可以随机存取其中的任何一个元素,并且支持在任意位置上进行插入和删除操作。在顺序表中,每个元素的下标都是唯一的,而且在顺序表中,相邻的元素在内存中也是相邻的。

        顺序表通常包含两个重要的属性:容量和长度。容量指该顺序表所能容纳的最大元素数量,而长度指当前已经存储的元素数量。当长度等于容量时,顺序表就已经满了,不能再插入元素。

2. 静态顺序表和动态顺序表的区别:

        由于顺序表底层是用数组完成的,所以这个数组决定了我们这个顺序表的大小,同时也区分出了静态顺序表与动态顺序表,下面我们来一一了解:

        静态顺序表:有着静态两字顾名思义则这个顺序表写好以后大小就固定死了,是不可以改变的(为了方便我们后期更改顺序表的类型,此处我们define定义一个变量,专门存放顺序表类型

typedef int SLDataTYpe;

typedef struct SeqList
{
	SLDataTYpe p[50];	//数组大小为50,代表这个顺序表可以存储50个元素
	int size;   //顺序表有效数据个数
	int capacity;	//顺序表空间大小
}SL;   //将顺序表struct SeqList取别名为SL

        动态顺序表:相较于静态,动态顺序表则在定义顺序表是写死数据的大小,而是定义了一个指针,等到后边需要用到顺序表的时候,再动态分配内存空间(C语言动态内存空间分配-CSDN博客)

typedef int SLDataTYpe;

typedef struct SeqList
{
	SLDataTYpe* p;
	int size;   //顺序表有效数据个数
	int capacity;	//顺序表空间大小
}SL;   //将顺序表struct SeqList取别名为SL

3. 顺序表的实现:

        在本次项目当中我们以动态顺序表为例,来对顺序表各类功能的实现,项目文件分为SeqList.h(顺序表中各类函数的声明),SeqList.c(顺序表各类功能的实现),SeqList_test(对应顺序表各类功能的测试),实现环境为VS2022

3.1. 顺序表的初始化:

        在SeqList.h声明一个函数用于实现顺序表的初始化,同时传入一个顺序表变量,SeqList.c实现顺序表的初始化,顺序表没被调用前,顺序表为NULL(注:要想调用SeqList.h中声明好的方法,则得包含该方法所在的头文件

SeqList.h:

#pragma once
#include <stdio.h>
typedef int SLDataTYpe;

//动态顺序表
typedef struct SeqList
{
	SLDataTYpe* p;
	int size;   //顺序表有效数据个数
	int capacity;	//顺序表空间大小
}SL;    //将顺序表struct SeqList取别名为SL

//顺序表的初始化
void SLInit(SL* ps);

SeqList.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"    //头文件包含

//顺序表初始化的实现
void SLInit(SL* ps)
{
	ps->p = NULL;   
	ps->size = 0;    //有效数据个数为0
	ps->capacity = 0;    //空间大小为0
}

  SeqList_test(在SeqList_test中调用SLInit函数,打开监视查看是否赋值成功):

void SLTest01()
{
	SL s1;
	SLInit(&s1);
	
}

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

测试结果:

(如上图所示,则初始化成功)

3.2. 顺序表的销毁:

        顺序表的销毁分为两种情况,一是顺序表已写入数据,二是没有写入数据

SeqList.h:

#pragma once
#include <stdio.h>
typedef int SLDataTYpe;

//动态顺序表
typedef struct SeqList
{
	SLDataTYpe* p;
	int size;   //顺序表有效数据个数
	int capacity;	//顺序表空间大小
}SL;    //将顺序表struct SeqList取别名为SL

//顺序表的初始化
void SLInit(SL* ps);

//顺序表的销毁
void SLDesttroy(SL* ps);

SeqList.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

//顺序表初始化的实现
void SLInit(SL* ps)
{
	ps->p = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

//顺序表的销毁
void SLDesttroy(SL* ps)
{
	if (ps->p)    //判断是否为NULL
	{
		free(ps->p);
	}
	ps->p = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

(由于代码量的缘故,后边只展示对应文件中要添加的代码)

3.3. 顺序表插入数据:

        为了方便展示,关于SeqList.h文件当中的代码,统一展示在此处

//顺序表头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataTYpe x);
void SLPushFront(SL* ps, SLDataTYpe x);

void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x);

//删除指定位置数据
void SLErase(SL* ps, int pos);

3.3.1. 头插:

头插可以分为以下几点:

1. 函数传参:

void SLPushFront(SL* ps, SLDataTYpe x);   //x为要插入的元素

2. 判断顺序表是否为空:

#include <assert.h>    //头文件包含
assert(ps);    //ps为要断言的变量

3. 判断顺序表空间是否够用:

由于后续我们要多次判断是否要增容,此处我们重新用一个函数完成顺序表的增容:

(注:realloc函数如果申请内存空间失败,则返回NULL,所以此处不可将realloc申请的空间直接赋给p->p这样会导致原来p->p中的数据全部清空,应先判断增容是否成功,再进行赋值)

void SLcheckCapacity(SL* p)
{
	//插入数据前判断空间是否足够 如果数组大小与内存总大小相等,则申请空间
	if (p->size == p->capacity)
	{
		//判断capacity的值是否为0,不为0则2倍增容
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		//增容空间
		SLDataTYpe* tmp = (SLDataTYpe*)realloc(p->p, 2 * newcapacity * sizeof(SLDataTYpe));
		//判断增容是否成功
		if (tmp == NULL)
		{
			perror("relloc fail");
			exit(1);
		}
		//申请成功以后
		p->p = tmp;
		p->capacity = newcapacity;
	}
}

4. 头部插入数据:

        假设一个数组中已有数据a,b,c,d,现在要在头部添加一个元素f,我们应该如何添加?

思路分析:

代码实现(SeqList.c):

void SLPushFront(SL* ps, SLDataTYpe x)
{
	//判断ps是否为NULL
	assert(ps);
	//判断内存空间是否足够,是否需要增容
	SLcheckCapacity(ps);
	//将顺序表中原有的数据整体往后挪一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->p[i] = ps->p[i - 1];
	}
    //添加元素
	ps->p[0] = x;
    //size向后挪动一位
	ps->size++;
}

3.3.2. 尾插:

         假设一个数组中已有数据a,b,c,d,现在要在最后添加一个元素f,我们应该如何添加?

思路分析:

代码实现(SeqList.c):

void SLPushBack(SL* ps, SLDataTYpe x)
{
	//判断ps是否为NULL
	assert(ps);
    //判断内存空间是否足够,是否需要增容
	SLcheckCapacity(ps);
	ps->p[ps->size++] = x;
	
}

3.3.3 头删:

        将除首地址的元素外其余所以元素往前挪动一位,同时size也需往前挪动一位(size--),覆盖首元素即可(注:如果数组中没有元素,即size=0,此时是没有元素可以删的,所以此处应还需断言size是否为0)

思路分析:

代码实现(SeqList.c):

void SLPopFront(SL* ps)
{
    //判断ps是否为NULL
	assert(ps);
    //判断数组是否为空
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->p[i] = ps->p[i + 1];
	}
	ps->size--;
}

3.3.4 尾删:

        当数组不为空时,size往前挪一位(注size代表的是数组的大小,即下标+1,也就是说size前边为整个数组,因此删除末尾元素时,我们只需要将size--即可)

思路分析:

代码实现(SeqList.c):

void SLPopBack(SL* ps)
{
	//断言
	assert(ps);
	//判断顺序表是否为NULL,为空删除等于-1,越界
	assert(ps->size);
	//删除数据
	ps->size--;
}

3.3.5 指定位置添加数据:

        与头插相类似,此处只需要将指定位置的数据整体往后挪一位size++,由于和头插相类似,就不在此处重复直接看代码:

void SLInsert(SL* ps, int pos, SLDataTYpe x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);	//判断pos的有效范围
	//插入数据:空间够不够
	SLcheckCapacity(ps);
	//让pos下标对应的数据,全部往后挪一位
	for (int i = ps->size; i > pos; i--)
	{
		ps->p[i] = ps->p[i - 1];
	}
	ps->p[pos] = x;
	ps->size++;

}

3.3.6 指定位置删除数据:

        与添加相反,删除指定对应数据以后,指定位置后的元素整体往前挪一位,size--

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

3.4 顺序表的打印:

        遍历数组

代码实现(SeqList.h  / SeqList.c):

//顺序表的打印
void SLPrintf(SL s);
void SLPrintf(SL s)
{
	//打印
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ", s.p[i]);
	}
	printf("\n");
}

3.5 顺序表的查找:

        遍历数组,查找对应的元素,存在返回元素的下标,不存在返回无效下标-1

代码实现(SeqList.h  / SeqList.c):

//查找
int SLFind(SL* ps, SLDataTYpe x);  //数据有,返回值的下标,否则返回-1
查找
int SLFind(SL* ps, SLDataTYpe x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->p[i] == x)
		{
			//找到了
			return i;
		}
	}
	//没找到
	return -1;
}

4.实现代码:

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataTYpe;
//动态顺序表
typedef struct SeqList
{
	SLDataTYpe* p;
	int size;   //顺序表有效数据个数
	int capacity;	//顺序表空间大小
}SL;

//顺序表的初始化
void SLInit(SL* ps);

//顺序表的销毁
void SLDesttroy(SL* ps);

//顺序表头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataTYpe x);
void SLPushFront(SL* ps, SLDataTYpe x);

void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x);

//删除指定位置数据
void SLErase(SL* ps, int pos);

//顺序表的打印
void SLPrintf(SL s);

//查找
int SLFind(SL* ps, SLDataTYpe x);  //数据有,返回值的下标,否则返回-1

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

//顺序表初始化的实现
void SLInit(SL* ps)
{
	ps->p = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

//顺序表的销毁
void SLDesttroy(SL* ps)
{
	if (ps->p)
	{
		free(ps->p);
	}
	ps->p = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

//增容
void SLcheckCapacity(SL* p)
{
	//插入数据前判断空间是否足够 如果数组大小与内存总大小相等,则申请空间
	if (p->size == p->capacity)
	{
		//判断capacity的值是否为0
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		//增容空间
		SLDataTYpe* tmp = (SLDataTYpe*)realloc(p->p, 2 * newcapacity * sizeof(SLDataTYpe));
		//判断增容是否成功
		if (tmp == NULL)
		{
			perror("relloc fail");
			exit(1);
		}
		//申请成功以后
		p->p = tmp;
		p->capacity = newcapacity;
	}
}

//顺序表的尾插
void SLPushBack(SL* ps, SLDataTYpe x)
{
	//判断ps是否为NULL
	assert(ps);
	SLcheckCapacity(ps);
	ps->p[ps->size++] = x;
	
}

//头插
void SLPushFront(SL* ps, SLDataTYpe x)
{
	//判断ps是否为NULL
	assert(ps);
	//增容
	SLcheckCapacity(ps);
	//将顺序表中原有的数据整体往后挪一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->p[i] = ps->p[i - 1];
	}
	ps->p[0] = x;
	ps->size++;
}

//顺序表的打印
void SLPrintf(SL s)
{
	//打印
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ", s.p[i]);
	}
	printf("\n");
}

//尾删
void SLPopBack(SL* ps)
{
	//断言
	assert(ps);
	//判断顺序表是否为NULL,为空删除等于-1,越界
	assert(ps->size);
	//删除数据
	ps->size--;
}

//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->p[i] = ps->p[i + 1];
	}
	ps->size--;
}

//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataTYpe x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);	//判断pos的有效范围
	//插入数据:空间够不够
	SLcheckCapacity(ps);
	//让pos下标对应的数据,全部往后挪一位
	for (int i = ps->size; i > pos; i--)
	{
		ps->p[i] = ps->p[i - 1];
	}
	ps->p[pos] = x;
	ps->size++;

}

//删除指定位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->p[i] = ps->p[i + 1];
	}
	ps->size--;
}

//查找
int SLFind(SL* ps, SLDataTYpe x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->p[i] == x)
		{
			//找到了
			return i;
		}
	}
	//没找到
	return -1;
}

SeqList_test.c(测试代码)

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

void SLTest01()
{
	SL s1;
	SLInit(&s1);
	
}

int main()
{
	SLTest01();
	return 0;
}
尾插
//SLPushBack(&s1, 1);
//SLPushBack(&s1, 2);
//SLPushBack(&s1, 3);
//SLPushBack(&s1, 4);
//SLPrintf(s1);
//SLPushBack(&s1, 5);
//SLPrintf(s1);
//SLPushFront(&s1, 5);
//SLPushFront(&s1, 6);
//SLPrintf(s1);
//
//
销毁
//SLDesttroy(&s1);

(有需要的小伙伴自取喔,最后还请点赞三联支持一下博主,Thanks♪(・ω・)ノ!!!)

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

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

相关文章

npm install 卡在reify:rxjs: timing reifyNode的解决办法

今天要逆向跑一个electron&#xff0c;但是npm install一直卡在 reify:element-plus: timing reifyNode:node_modules/lodash Completed in 6664ms这里一动不动&#xff0c;一番研究之后发现可能跟用的镜像有关系&#xff0c;我原本是官方镜像&#xff0c;总感觉第三方镜像有一…

mysql主从热备部署

1、主从复制原理 mysql之间数据复制的基础是二进制日志文件。一台mysql数据库一旦开启用日志文件后&#xff0c;其作为master&#xff0c;它的数据库所有操作都会以事件的方式记录在二进制日志中&#xff0c;其他数据库作为slave通过一个I/O线程与主数据库保持通信&#xff0c;…

MATLAB蚁群算法求解带时间窗的旅行商TSPTW问题代码实例

MATLAB蚁群算法求解带时间窗的旅行商TSPTW问题代码实例 蚁群算法编程求解TSPTW问题实例&#xff1a; 在经纬度范围为(121, 43)到(123, 45)的矩形区域内&#xff0c;散布着1个商家&#xff08;编号1&#xff09;和25个顾客点&#xff08;编号为226&#xff09;&#xff0c;各个…

【Linux】用户组、用户、文件权限(ugo权限),权限掩码,chmod,chown,suid,sgid,sticky,su,sudo

用户组 注意&#xff1a;普通用户只能查看有哪些组&#xff0c;不能创建/修改/删除&#xff0c;会提示&#xff1a;用户名 is not in the sudoers file.This incident will be reported. groupadd 用户组名新建用户组cat /etc/group查看有哪些组&#xff08;普通用户可以操作…

python模拟QQ聊天的代码

以下是一个简单的Python模拟QQ聊天的代码示例&#xff1a; python # 导入QQ消息包 import tqq # 创建QQ客户端对象 client tqq.TQQClient() # 连接QQ服务器 client.connect("你的QQ号码", "你的QQ密码") # 创建一个QQ会话对象 session client.session() …

字符串函数(二):strlen(求长度),strstr(查找子串),strtok(分割),strerror(打印错误信息)

字符串函数 一.strlen&#xff08;求字符串长度&#xff09;1.函数使用2.模拟实现&#xff08;三种方法&#xff09; 二.strstr&#xff08;字符串查找子串&#xff09;1.函数使用2.模拟实现 三.strtok&#xff08;字符串分割&#xff09;四.strerror&#xff0c;perror&#x…

BLDC电机基础知识

1、电机工作原理 电机输入的是电能输出机械能&#xff0c;即电机是一种将电能转换为机械能的装置。电机利用磁场的同名磁极互相排斥以及电磁场原理完成电能与机械能的转换。 由物理电磁场理论知识我们知道&#xff0c;磁铁周围存在磁场&#xff0c;同时运动的电荷或通电导线周…

【强训笔记】day22

NO.1 思路&#xff1a;将情况全部枚举出来。 代码实现&#xff1a; #include <iostream> #include<string> using namespace std;string a,b; int main() {cin>>a>>b;int ma.size(),nb.size();int retm;for(int i0;i<n-m;i){int tmp0;for(int j…

Linux修改终端命令颜色

1.在家目录中修改.bashrc文件 cd ~ vim .bashrc2.找到PS1相关段落&#xff0c;把其他的注释掉&#xff0c;填上该行代码&#xff0c;修改为自己设置的颜色 (具体颜色查看参考文章) 提供两种颜色&#xff0c;其他的自学调色盘吧(下文有)~ (祝你愉快) ①浅蓝色 深蓝 PS1\[\03…

知识图谱 | 语义网络写入图形数据库(含jdk和neo4j的安装过程)

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要介绍如何使用 Neo4j 图数据库呈现语义网络&#xff0c;并通过 Python 将语义网络的数据写入数据库。具体步骤包括识别知识中的节点和关系&#xff0c;将其转化为图数据库的节点和边&#xff0c;最后通过代码实现数据的写…

pytorch学习(一):tensorboard使用

第一次使用需要加入 pip install tensorboard安装后&#xff0c;就可以使用tensorboard&#xff1b; from torch.utils.tensorboard import SummaryWriterwriterSummaryWriter("logs")# writer.add_image() for i in range(100):writer.add_scalar("yx",…

JWT令牌技术实现登录校验

一.简单登录功能 在登录界面中&#xff0c;我们可以输入用户的用户名以及密码&#xff0c;然后点击 "登录" 按钮就要请求服务器&#xff0c;服务端判断用户输入的用户名或者密码是否正确。如果正确&#xff0c;则返回成功结果&#xff0c;跳转至系统首页面。 1.功能…

LeetCode1657确定两个字符串是否接近

题目描述 如果可以使用以下操作从一个字符串得到另一个字符串&#xff0c;则认为两个字符串 接近 &#xff1a; 操作 1&#xff1a;交换任意两个 现有 字符。例如&#xff0c;abcde -> aecdb操作 2&#xff1a;将一个 现有 字符的每次出现转换为另一个 现有 字符&#xff0…

智慧公厕系统:改变“上厕所”体验的科技革新

公共厕所是城市建设中不可或缺的基础设施&#xff0c;然而&#xff0c;由于较为落后的管理模式&#xff0c;会常常存在着管理不到位、脏乱差的问题。为了改善公厕的使用体验&#xff0c;智慧公厕系统应运而生&#xff0c;并逐渐成为智慧城市建设的重要组成部分。本文将以智慧公…

6. RedHat认证-基于公钥的认证方式

6. RedHat认证-基于公钥的认证方式 主要学习客户端访问服务端的时候&#xff0c;免密登录这一方式 注意: 免密登录只是基于公钥认证的一个附带属性(基于公钥认证的方式更加安全&#xff0c;防止黑客暴力破解) 第一步&#xff1a;将客户端生成的秘钥传送到服务器 在客户端通过…

display:flex align-items:center无效的不一样的解决思路

写H5的时候&#xff0c;希望两个元素在div中垂直居中&#xff0c;但是设置align-items:center无效&#xff0c;最终排查原因是引入三方css影响了align-items:center。 具体分析如下&#xff0c;想让搜索图标和input在div里水平居中&#xff1a; 布局如下&#xff1a; <div…

实验十 智能手机互联网程序设计(微信程序方向)实验报告

实验目的和要求 完成以下页面设计。 二、实验步骤与结果&#xff08;给出对应的代码或运行结果截图&#xff09; Wxml <view class"container"> <view class"header"> <view class"logo"…

MHD093C-058-PG1-AA具备哪些特点?

MHD093C-058-PG1-AA是一种高性能的伺服电机控制器。 该产品具备以下特点&#xff1a; 高精度与高性能&#xff1a;MHD093C-058-PG1-AA设计用于提供精确的运动控制和定位&#xff0c;适用于需要高精度定位和控制的场合。快速响应&#xff1a;采用先进的控制技术&#xff0c;确…

C++类与对象基础探秘系列(二)

目录 类的6个默认成员函数 构造函数 构造函数的概念 构造函数的特性 析构函数 析构函数的概念 析构函数的特性 拷贝构造函数 拷贝构造函数的概念 拷贝构造函数的特性 赋值运算符重载 运算符重载 赋值运算符重载 const成员 const修饰类的成员函数 取地址及const取地址操作…

扫码枪与Input的火花

文章目录 前言一、需求&#xff1a;交互细节二、具体实现两个核心的函数&#xff1a;自动聚焦 三&#xff0c;扩展知识input 与 change的区别 前言 在浏览器扫描条形码获取条形的值&#xff0c;再操作对应的逻辑。这是比较常见的业务&#xff0c;这里记录实际操作。 其中PC端…