【数据结构】——顺序表(增删查改)

news2024/11/24 12:45:18

 

目录

 前言:

顺序表: 

1、概念及分类 

1.1顺序表分类

静态顺序表

动态顺序表

 2、接口实现

2.1功能要求

2.2功能实现 

💡初始化顺序表

 💡销毁顺序表

 💡顺序表尾插入

💡检查是否扩容 

💡打印顺序表 

 💡顺序表头插入

💡顺序表头删除

💡顺序表尾删除

💡顺序表pos位置插入值

 💡顺序表删除pos的位置

 总代码

test.c

 SeqList.c

 SeqList.h


 

 前言:

数据结构是计算机存储、组织数据的方式。 

数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么方式构成,以及数据元素之间呈现的结构。

能够存储数据(如顺序表、链表等结构)
存储的数据能够方便查找

顺序表: 

数据结构分为:线性表非线性表

        顺序表就是线性表中的一个小类。

何为线性表:线性表是指n个具有相同性质的数据元素的有限序列,

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

注:线性表的物理结构不一定是线性的,它在逻辑结构上一定是线性的(这个很好理解,等我们学完顺序表和单链表这对黄金搭档,就明白这句话的含义了。(逻辑结构类似于想象的,比如箭头这种东西在内存中是存在的))

顺序表是线性表,顺序表在逻辑结构和物理结构上都是线性的。 

 

1、概念及分类 

顺序表(SeqList):顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构连续存储数据,不能跳跃)。 

类似于数组,但是顺序表是连续的(只能从头开始连续),数组不需要连续;

1.1顺序表分类

静态顺序表

概念:使用定长数组存储元素

缺陷:空间给少了不够⽤,给多了造成空间浪费

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

 

动态顺序表

概念:使用动态开辟的数组存储。 

//动态顺序表
typedef int SLDateType;
typedef struct SeqList
{
    SLDateType* array;  //指向动态开辟的数组
    size_t size;  //数据中存储的数据
    size_t capacity;   //数组的容量
}SeqList;

 

建议用动态顺序表,比起静态顺序表,动态的更加好调整顺序表的大小。接下来,我也会以动态顺序表为例,介绍如何实现动态顺序表的增删查改。 

 2、接口实现

2.1功能要求

#pragma once
#include<stdio.h>
#include<assert.h>

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

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

//对顺序表的打印
void SeqListPrint(SL* ps);

//对顺序表的尾插入
void SeqListPushBack(SL* ps, SLDataType x);

//对顺序表的头插入
void SeqListPushFront(SL* ps, SLDataType x);

//对顺序表头删除
void SeqListPopFront(SL* ps);

//对顺序表的尾删除
void SeqListPopBack(SL* ps);

// 顺序表查找
//int SeqListFind(SeqList* ps, SLDateType x);
 
// 顺序表在pos位置插入x
void SeqListInsert(SL* ps, int pos, SLDataType x);


// 顺序表删除pos位置的值
void SeqListErase(SL* ps, int pos);

2.2功能实现 

💡初始化顺序表

没啥好说的,在【C语言】系列都讲过了,3 2 1 上链接

//初始化
void SeqListInit(SL* ps)
{
	assert(ps);
	ps->arry = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
 💡销毁顺序表
//销毁
void SeqListDestroy(SL* ps)
{
	assert(ps);
	if (ps->arry != NULL)
	{
		free(ps->arry);
		ps->arry = NULL;
		ps->size = 0;
		ps->capacity = 0;
	}
}
 💡顺序表尾插入

这里需要检查是否需要扩容,我们还需要提前封装一个函数

//对顺序表的尾插入
void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	//检查是否需要扩容
	CheckCapacity(ps);
	ps->arry[ps->size] = x;
	ps->size++;
}
💡检查是否扩容 

在这里需要注意的就是,我们初始化的时候,capacity是0,如果用常规*2方式扩容,0*2还是0;

所以这里可以用上一个三目操作符来避免;realloc可以对空指针进行开辟空间,相当于malloc

 

//检查是否需要扩容
void CheckCapacity(SL* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)	//需要扩容
	{
		int new =ps->capacity == 0 ? 4 :ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arry, sizeof(SLDataType)*new);
		//检查是否扩容成功
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		ps->arry = tmp;
		ps->capacity = new;
		printf("扩容成功\n");
	}
}
💡打印顺序表 
//打印顺序表
void SeqListPrint(SL* ps)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arry[i]);
	}
	printf("\n");
}
 💡顺序表头插入

不管是头插入还是尾插入以及后面的任意位置插入,都需要检查是否需要扩容,

头插入就相当于先将数据往右边移动,头位置空出来,然后将新数据插入即可

//头插入
void SeqListPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	CheckCapacity(ps);
	int begin = ps->size;
	while (begin>0)
	{
		ps->arry[begin] = ps->arry[begin - 1];
		begin--;
	}
	ps->arry[0] = x;
	ps->size++;
}
💡顺序表头删除

 因为顺序表的逻辑结构和物理结构一致,数据前后紧密相连的,所以可以直接将数据往前覆盖

//头删除
void SeqListPopFront(SL* ps)
{
	assert(ps);
	int begin = 1;
	while (begin > 0 &&  begin < ps->size )
	{
		ps->arry[begin - 1] = ps->arry[begin];
		begin++;
	}
	ps->size--;
}
💡顺序表尾删除

需要注意的就说size跑到负数去,我们采取“七匹狼式警告”,直接“竹条炒肉”

//尾删除
void SeqListPopBack(SL* ps)
{
	assert(ps);
	//对size检查 防止越界
	assert(ps->size > 0);
	ps->size--;
}
💡顺序表pos位置插入值

在容量内任意位置插入,将该位置后的数据往后移,将新元素赋值

// 顺序表在pos位置插入x
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	CheckCapacity(ps);
	int begin = ps->size;
	while (begin > pos)
	{
		ps->arry[begin] = ps->arry[begin - 1];
		begin--;
	}
	ps->arry[pos] = x;
	ps->size++;
}
 💡顺序表删除pos的位置
// 顺序表删除pos位置的值
void SeqListErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->arry[begin] = ps->arry[begin + 1];
		begin++;
	}
	ps->size--;
}

 总代码

注意,我们完成每个功能实现,最好都单独测试一下,不要留到最后,不然就会这样

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//11-4ݽṹ
#include<stdio.h>

void test1()
{
	SL s1;
	SeqListInit(&s1);
	SeqListPushBack(&s1,1);
	SeqListPrint(&s1);

	SeqListDestroy(&s1);
}

void test2()
{
	SL s2;
	SeqListInit(&s2);
	SeqListPushBack(&s2, 1);
	SeqListPushBack(&s2, 2);
	SeqListPushBack(&s2, 3);
	SeqListPushBack(&s2, 4);
	SeqListPushBack(&s2, 5);

	SeqListPushFront(&s2,10);
	SeqListPrint(&s2);
	
}

//void test3()
//{
//	SL s3;
//	SeqListInit(&s3);
//	SeqListPushBack(&s3, 1);
//	SeqListPushBack(&s3, 2);
//	SeqListPushBack(&s3, 3);
//	SeqListPushBack(&s3, 4);
//	SeqListPushBack(&s3, 5);
//	SeqListPrint(&s3);
//
//	SeqListPopFront(&s3);
//	SeqListPrint(&s3);
//}

void test4()
{
	SL s4;
	SeqListInit(&s4);
	SeqListPushBack(&s4, 1);
	SeqListPushBack(&s4, 2);
	SeqListPushBack(&s4, 3);
	SeqListPushBack(&s4, 4);
	SeqListPushBack(&s4, 5);
	SeqListPrint(&s4);

	SeqListInsert(&s4, 2, 66);
	SeqListPrint(&s4);
}
void test5()
{
	SL s5;
	SeqListInit(&s5);
	SeqListPushBack(&s5, 1);
	SeqListPushBack(&s5, 2);
	SeqListPushBack(&s5, 3);
	SeqListPushBack(&s5, 4);
	SeqListPushBack(&s5, 5);
	SeqListPrint(&s5);
	SeqListErase(&s5, 2);
	SeqListPrint(&s5);
}
int main()
{ 
	//test1();
	//test2();
	//test3();
	//test4();
	test5();
	return 0;
}

 SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//初始化
void SeqListInit(SL* ps)
{
	assert(ps);
	ps->arry = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//销毁
void SeqListDestroy(SL* ps)
{
	assert(ps);
	if (ps->arry != NULL)
	{
		free(ps->arry);
		ps->arry = NULL;
		ps->size = 0;
		ps->capacity = 0;
	}
}
//检查是否需要扩容
void CheckCapacity(SL* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)	//需要扩容
	{
		int new =ps->capacity == 0 ? 4 :ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->arry, sizeof(SLDataType)*new);
		//检查是否扩容成功
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		ps->arry = tmp;
		ps->capacity = new;
		printf("扩容成功\n");
	}
	
}
//对顺序表的尾插入
void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	//检查是否需要扩容
	CheckCapacity(ps);
	ps->arry[ps->size] = x;
	ps->size++;
}
//打印顺序表
void SeqListPrint(SL* ps)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arry[i]);
	}
	printf("\n");
}
//头插入
void SeqListPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	CheckCapacity(ps);
	int begin = ps->size;
	while (begin>0)
	{
		ps->arry[begin] = ps->arry[begin - 1];
		begin--;
	}
	ps->arry[0] = x;
	ps->size++;
}
//头删除
void SeqListPopFront(SL* ps)
{
	assert(ps);
	int begin = 1;
	while (begin > 0 &&  begin < ps->size )
	{
		ps->arry[begin - 1] = ps->arry[begin];
		begin++;
	}
	ps->size--;
}
//尾删除
void SeqListPopBack(SL* ps)
{
	assert(ps);
	//对size检查 防止越界
	assert(ps->size > 0);
	ps->size--;
}

// 顺序表在pos位置插入x
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	CheckCapacity(ps);
	int begin = ps->size;
	while (begin > pos)
	{
		ps->arry[begin] = ps->arry[begin - 1];
		begin--;
	}
	ps->arry[pos] = x;
	ps->size++;
}

// 顺序表删除pos位置的值
void SeqListErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->arry[begin] = ps->arry[begin + 1];
		begin++;
	}
	ps->size--;

 SeqList.h

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

typedef struct SeqList
{
	SLDataType* arry;	//动态开辟的数组
	int size;	//记录个数
	int capacity;	//记录容量
}SL;



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

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

//对顺序表的打印
void SeqListPrint(SL* ps);

//对顺序表的尾插入
void SeqListPushBack(SL* ps, SLDataType x);

//对顺序表的头插入
void SeqListPushFront(SL* ps, SLDataType x);

//对顺序表头删除
void SeqListPopFront(SL* ps);

//对顺序表的尾删除
void SeqListPopBack(SL* ps);

// 顺序表查找
//int SeqListFind(SeqList* ps, SLDateType x);
 
// 顺序表在pos位置插入x
void SeqListInsert(SL* ps, int pos, SLDataType x);


// 顺序表删除pos位置的值
void SeqListErase(SL* ps, int pos);

 

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

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

相关文章

科技创意赋能乡村文旅振兴

近日&#xff0c;由北京大学创意产业研究中心联合中国国际科技促进会新基建专委会共同主办的“科技创意赋能乡村振兴研讨会”在京举行&#xff0c;与会专家学者围绕“和美乡村共同富裕智慧文旅”主题进行深入探讨。北京大学创意产业研究中心副主任吕艺、国家文化和旅游公共服务…

Python点云处理(十九)点云地面点提取——CSF布料模拟算法

目录 0 简述1 算法原理2 具体步骤3 实现0 简述 对于点云地面点滤波,众多传统算法滤波效果容易受到地形特征的影响(通常在复杂场景及陡峭地形区域滤波效果较差)且常常需要用户对数据有较为丰富的先验知识来进行设置滤波器中的各种参数。为了解决这些问题,张吴明教授等人提出…

Allegro如何快速将目标旋转90度操作指导

Allegro如何快速将目标旋转90度操作指导 在用Allegro进行PCB设计的时候,时常需要目标旋转90度,我们常用的命令是Spin,如下图以旋转电阻为例 点击Edit点击SpinOp

数据结构初阶---复杂度的OJ例题

复杂度的OJ例题 一、消失的数字1.思路一2.思路二3.思路三 二、旋转数组1.思路一2.思路二3.思路三 一、消失的数字 数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(N)时间内完成吗&#xff1f; 链接&#xff1a;力扣&…

用「埋点」记录自己,不妄过一生

最近有朋友问我「埋点怎么做」&#xff0c;给朋友讲了一些互联网广告的案例&#xff0c;从源头的数据采集讲到末尾的应用分析和流量分配等&#xff08;此处省略N多字&#xff09; 解释完以后&#xff0c;我想到一个问题&#xff1a;有了埋点可以做分析&#xff0c;那我们对自己…

尚硅谷大数据项目《在线教育之实时数仓》笔记006

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第9章 数仓开发之DWD层 P041 P042 P043 P044 P045 P046 P047 P048 P049 P050 P051 P052 第9章 数仓开发之DWD层 P041 9.3 流量域用户跳出事务事实表 P042 DwdTrafficUserJum…

Android岗位居然要求有鸿蒙开发的需求了?HarmonyOS它来了

鸿蒙才开发几年,就已经让对手们脊背发凉了&#xff0c;要知道主流操作系统都是积累几十年的产物。 以苹果MacOS为例,其前身NextStep是85年开干的。另一家微软公司,Win95爆卖的时候,中国还没加入WTO。 大家使用过鸿蒙系统产品的,应该能直观感觉到它的流畅性,易用性,如果你有个…

leetcode刷题日记:70.Climbing Stairs(爬楼梯)

给了我们n阶楼梯让我们去爬&#xff0c;每次只能爬1阶或2阶&#xff0c;这个我们可以使用递归的方法进行解决&#xff0c;向上爬的过程与向下降的过程是一样的&#xff0c;所以我们就可以这样考虑&#xff0c;现在就是n阶楼梯每一次下降1阶或2阶有多少种方法刚好下降到0阶。 i…

IDEA取消git对项目的版本控制

前言 前几天新建项目的时候不小心选了个git仓库&#xff0c;导致这个测试项目一直被git管理着。 解决办法 1 右键项目 选择打开资源目录 2 删除.git文件 把目录下的.git文件删掉 3 删除idea中的git管理 删除完.git文件后&#xff0c;进入idea&#xff0c;右下角会有这样的提…

ElementUI-tree拖拽功能与节点自定义

前言 在管理端会遇到多分类时&#xff0c;要求有层次展示出来&#xff0c;并且每个分类有额外的操作。例如&#xff1a;添加分类、编辑分类、删除、拖到分类等。 下面将会记录这样的一个需求实习过程。 了解需求 分类展示按层级展示分类根据特定的参数展示可以操作的按钮&a…

cookie、session和Token的区别?JWT又是什么?单点登录又是什么?头大?快进来看看,一文帮你捋清楚~

目录 0、HTTP是无状态的 1、前端标记cookie 1.1、cookie限制空间范围 1.2、cookie限制时间范围 1.3、cookie限制使用方式 2、服务端存储session库 2.1、我们先来简单聊聊session是什么&#xff1f; 2.2、session的存储方式 2.3、session的过期和销毁 2.4、session的分…

操作系统:文件管理(二)文件系统

一战成硕 4.3 文件系统4.3.1 文件系统结构4.3.2 文件系统布局4.3.3 外存空闲空间管理4.3.4 虚拟文件系统 4.3 文件系统 4.3.1 文件系统结构 4.3.2 文件系统布局 文件系统在磁盘中的结构 文件系统在内存中的结构 内存中的信息用于管理文件系统并通过缓存提高性能&#xff0c;这…

HDFS系统权限详解

一&#xff0c;HDFS超级用户 启动namenode的用户就是HDFS中的超级用户 如图所示 HDFS中&#xff0c;也是有权限控制的&#xff0c;其控制逻辑和Linux文件系统的完全一致 但是不同的是&#xff0c;两个系统的Supergroup不同(超级用户不同) Linux的操作用户是root HDFS文件系统的…

AI 编程界的扛把子

大家好&#xff0c;我是伍六七。 全国最大 AI 社群《AI 破局俱乐部》初创合伙人。8 年 Java 经验&#xff0c;干过开发&#xff0c;也做过管理。目前在某互联网大厂从事 Java 开发&#xff0c;业余时间研究 AI 编程。 我从 2022 年底&#xff0c;ChatGPT 问世&#xff0c;就密…

K8S知识点(五)

&#xff08;1&#xff09;资源管理介绍 Pod控制器的作用&#xff0c;就是为了最终产生各种各样的Pod&#xff0c;Pod里面运行容器&#xff0c;容器里面运行程序 程序需要数据持久化&#xff0c;可以用数据存储卷来存储 Pod想要让外部访问需要通过Service代理&#xff0c;外部…

基于Pytorch框架的LSTM算法(一)——单维度单步预测(1)

1.项目说明 使用data中的close列的时间序列数据完成预测【使用close列数据中的前windowback-1天数据完成未来一天close的预测】 2.数据集 Date,Open,High,Low,Close,Adj Close,Volume 2018-05-23,182.500000,186.910004,182.179993,186.899994,186.899994,16628100 2018-05…

IDEA高效调试,你真的会了吗

大家好&#xff0c;这里是 一口八宝周 &#x1f44f; 欢迎来到我的博客 ❤️一起交流学习 文章中有需要改进的地方请大佬们多多指点 谢谢 &#x1f64f; 由于平时工作中经常需要debug调试代码&#xff0c;每次调试都会阻塞住进程&#xff0c;影响别人排查问题。 “你一个人deb…

Linux生成动态库

动态库 1.命名规则 Linux&#xff1a; libxxx.so lib &#xff1a;前缀&#xff08;固定的&#xff09;&#xff1b;xxx&#xff1a;动态库的名字&#xff08;自己取&#xff09;&#xff1b;.so&#xff1a;后缀&#xff08;固定的&#xff09;&#xff1b; Windows&#…

.NET Framework中自带的泛型委托Action

Action<>是.NET Framework中自带的泛型委托&#xff0c;可以接收一个或多个输入参数&#xff0c;但不返回任何参数&#xff0c;可传递至多16种不同类型的参数类型。在Linq的一些方法上使用的比较多。 1、Action泛型委托 .NET Framework为我们提供了多达16个参数的Action…

链表面试OJ题(1)

今天讲解两道链表OJ题目。 1.链表的中间节点 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个…