首页 > 编程语言 >数据结构与算法——顺序表

数据结构与算法——顺序表

时间:2024-12-08 16:27:55浏览次数:7  
标签:ps arr 顺序 int SLDataType 算法 数据结构 size

前言

本章讲解线性表中最基础的顺序表,觉得有用的话记得点点关注。

正文

1. 线性表

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

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

逻辑上连续体现在线性表的呈现,线性表在屏幕上是以连续形式呈现,故为线性结构。
物理结构上不一定连续体现在线性表的内存形式。因为每个元素储存的地址大概率不是连续的,而是随机分布在线性表所申请的空间中。

2. 顺序表

2.1 概念与结构

概念:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。(顺序表的底层结构是数组

顺序表=数组+增加数据+删除数据+修改数据+查找数据+ …

顺序表分为静态顺序表和动态顺序表。根据不同场景创建顺序表。
前者空间有限,申请小了不够用,申请多了用不完,后者需要动态申请空间,因此需要malloc calloc realloc 之一。
malloc:一次申请连续空间。
calloc:同malloc,还会初始化。
realloc:同malloc,还会扩容。
因此,动态顺序表用realloc动态申请内存。

静态顺序表:

//静态顺序表
typedef int SLDataType;
#define N 7
typedef struct SeqList {
	SLDataType a[N];
	int size;//有效数据个数

}SL;

动态顺序表:

// 动态顺序表 -- 按需申请
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;//有效数据个数
	int capacity;//空间大小
}SL;

关于上述代码typedef int SLDataType;
此处重定义int为了方便更改顺序表里元素的类型,如果需要更改,只要将int更改即可。

2.2 顺序表的初始化

初始化顺序表的成员arr,size,capacity
size:顺序表初始化时输入数据在数组中的位置。
capacity:数组中数组空间的最大值。

//创建顺序表
typedef int SLDataType;
typedef struct SeqList {
	SLDataType* arr;
	int size;
	int capacity;
}SL;
//顺序表初始化
void SLInit(SL* ps)
{
	ps.arr = NULL;
	ps.size = ps.capacity = 0;
}
//测试代码,检测是否有误
void test01()
{
	SL s1;
	SLInit(&s1);//传址调用
}
//main函数
int main()
{
	test01();
	return 0;
}

传址调用(取地址):形参的改变会影响到实参。
传值调用(不取地址):形参改变不会影响到实参。

2.3 顺序表的数据插入

尾插

尾插之前需要判断顺序表空间是否足够,若不够,则需要realloc扩容。
关于realloc,一般成2倍扩容。因为用++(前置++/后置++)扩容时,如果堆区的数组后面的空间小于扩容需求,则数组会在堆区找更大的空间,接着拷贝旧数据,释放旧空间,把数据粘贴到新空间,所以用二倍扩容,避免多次拷贝释放粘贴。

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps->size == ps->capacity)
	{
		ps->arr = (SLDataType*)realloc(ps->arr, 2 * ps->capacity);
	}
	ps->arr[ps->size++] = x;
}

以上代码又有什么问题呢?
capacity初始为0;空间可能申请失败;realloc第二个参数的单位是字节…

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps->size == ps->capacity)
	{
	//解决capacity初始为0的问题
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
	//解决realloc第二个参数的单位是字节的问题
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * 4);
	//解决空间可能申请失败的问题
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	ps->arr[ps->size++] = x;
}

时间复杂度O(1)
温馨提示:写完尾插之后记得调用函数SLPushBack(SLpsSLDataType x)运行测试。

头插
//判断空间是否满了
void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
	SLCheckCapacity(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
}

如果如下传参,程序就崩了,而且退出码是随机数。
所以需要判断一下传的指针是否为空。

	SLPushFront(NULL, 1);

修改后:

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	/*温柔的处理方式
	if (ps == NULL)
	{
		return;
	}*/
	//assert(表达式)表达式为真,程序继续进行;为假,报错。
	assert(ps);
	SLCheckCapacity(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
}

时间复杂度O(N)
温馨提示:写完头插之后记得调用函数SLPushFront(SLpsSLDataType x)运行测试。

数据插入后的顺序表:
size:顺序表初始化时输入数据在数组中的位置,也是顺序表中有效数据个数。
capacity:数组中数组空间的最大值。
在这里插入图片描述

2.4 顺序表的数据删除

删除不一定要将数据覆盖为0,也可以将数据标记为空。

尾删
//尾删
void SLPopBack(SL* ps)
{
    //顺序表不为空
	assert(ps && ps->size);
	//有效数据减1,故size--
	--ps->size;
}

时间复杂度O(1)
尾删只需要将最后一个标记为空,故将有效数据个数减1。
温馨提示:写完尾删之后记得调用函数SLPopBack(SLps)运行测试。

头删
//头删
void SLPopFrnt(SL* ps,int size)
{
    //顺序表不为空
	assert(ps && ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	//有效数据减1,故size--
	--ps->size;
}

时间复杂度O(N)
头删只需将第二个数据赋值给第一个数据,第三个赋值给第二个…依次遍历
温馨提示:写完头删之后记得调用函数SLPopFront(SLpsint size)运行测试。

2.5 关于顺序表的其他操作

对顺序表有兴趣的可以自行探索其他操作。

数据查找
//数据查找
//找到了,返回下标;未找到,返回-1
int SLFind(SL* ps,SLDataType x)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			return i;
		}
	}
	return -1;
}

温馨提示:记得测试。

指定位置之前插入数据
//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos <= 0 && pos <= ps->size);

	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	++ps->size;
}

温馨提示:记得测试。

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

温馨提示:记得测试。

销毁
//销毁
void SLDesTroy(SL* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

标签:ps,arr,顺序,int,SLDataType,算法,数据结构,size
From: https://blog.csdn.net/2401_87035328/article/details/144316947

相关文章

  • 调整数组顺序使奇数位于偶数前面
    题目输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)解法双指针i和j指针i起点是数组起点,当i检测到偶数时停下。j的起点时数组终点,当j检测到奇数时停下,交换i和j处的元素。如图,2和9交换。packag......
  • 【算法】【优选算法】位运算(上)
    目录一、位运算简介及常用操作二、191.位1的个数三、338.比特位计数四、461.汉明距离五、136.只出现一次的数字六、260.只出现一次的数字III一、位运算简介及常用操作基础位运算:右移:>>左移:<<按位取反:~按位与:&:有0就是0按位或:|:有1就是1按位异或:^:相同为0......
  • 【算法】【优选算法】字符串
    目录一、14.最⻓公共前缀二、5.最⻓回⽂⼦串三、67.⼆进制求和四、43.字符串相乘一、14.最⻓公共前缀题目链接:14.最⻓公共前缀题目描述:解题思路:思路一:我们直接两两求一下公共前缀,记录在ret字符串中,然后ret与后续继续求公共前缀,最后的ret就是结果求公共前缀,......
  • 高阶数据结构--B树&&B+树实现原理&&B树模拟实现--Java
    目录一、B-树概念二、B-树插入分析1.用序列{53,139,75,49,145,36,101}构建B树的过程如下:2.插入过程总结三、B树插入实现四、B+树1.B+树概念2.B+树的特性 五、B+树应用1.索引 2.Mysql索引3.InnoDB一、B-树概念1970年,R.Bayer和E.mccreight提出了......
  • [待更新]欧几里得算法(辗转相除法)与拓展欧几里得算法
    更新日志2024/12/08:开工。欧几里得算法用途与原理欧几里得算法,用于求两个数的最大公约数。其核心原理为:\(\gcd(a,b)=\gcd(b,a\bmodb)\)证明首先,我们证明\(\gcd(a,b)=\gcd(b,a\bmodb)\)。为了方便证明,这里我们令\(a>b\)。\[\because\gcd(a,b)\mida\text,\gcd......
  • 【C++算法】33.位运算_判定字符是否唯一
    文章目录题目链接:题目描述:解法C++算法代码:图解题目链接:面试题01.01.判定字符是否唯一题目描述:解法如果使用数据结构的话哈希表:一个一个字符扫描,不在哈希表里面的就放进去,在里面的就返回false。扫描完全部不重复就返回true。也可以优化一下,字母一共26......
  • 【C++算法】34.位运算_丢失的数字
    文章目录题目链接:题目描述:解法C++算法代码:题目链接:268.丢失的数字题目描述:解法哈希表创建一个0~5的数组从前往后遍历一下,有的数字就在表里面标记一下,最后看一下哪些数字没有被标记过。高斯求和先求出应该有的和:(首项+末项)*项数÷2然后减去数组的和......
  • 机器学习(4)Kmeans算法
    1、简述聚类分析的重要性及其在机器学习中的应用  聚类分析,作为机器学习领域中的一种无监督学习方法,在数据探索与知识发现过程中扮演着举足轻重的角色。它能够在没有先验知识或标签信息的情况下,通过挖掘数据中的内在结构和规律,将数据对象自动划分为多个类别或簇。每个簇内的......
  • 算法日记 43-44 day 图论(深搜,广搜)
    直接看题目,还是熟悉写法。题目:孤岛的总面积101.孤岛的总面积(kamacoder.com)题目描述给定一个由1(陆地)和0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。现在......
  • 地平线 bev 参考算法板端一致性验证教程
    01前言由于部署时数据来源的硬件不同以及应用开发的高效性要求,往往会使得在板端部署阶段的数据准备操作与训练时有所差异,导致在同样的输入下,量化模型的输出结果和板端部署模型的输出结果不一致。本文将基于开发者社区中已经发布的地平线bev参考算法板端输入数据准备教程,以be......