【C语言数据结构(基础篇)】第二站:顺序表

news2024/11/17 1:55:24

目录

一、线性表

 二、顺序表的实现(概念以及静态顺序表)

1.创建三个工程文件

2.顺序表的概念

3.顺序表的定义

4.初始化顺序表

5.静态顺序表的尾插

三、顺序表的实现(升级为动态顺序表)

1.动态顺序表的定义

2.动态顺序表的初始化

3.动态顺序表的尾插

4.顺序表的头插

 5.顺序表的尾删

 6.顺序表的头删

 7.顺序表任意位置的增加

8.顺序表任意位置的删除

 9.顺序表的销毁

10.顺序表的查找

 11.顺序表的修改

 12.顺序表的菜单

 三、顺序表完整代码

总结


一、线性表

首先我们必须要了解的一个概念是线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表就是数组 ,他的内存是连续的

下面就是一个链表的结构,当然或许你现在并不知道链表是什么,但是没有关系, 我们在后面的文章中将会花费大量的笔墨去详细讲解链表,这里你只需要大概看一眼就可以了,下图什么都看不懂是没有任何关系的。

 二、顺序表的实现(概念以及静态顺序表)

对于顺序表的实现,我们采用分文件的形式来展现,在前面我们也已经利用了两个小游戏来让大家熟悉了分文件的写法,这里就不在赘述。如果还有不懂的地方,可以去C语言专栏去找到对应的文章。同样数据结构部分,为了规范我们的写法,我们全部采用大驼峰的命名风格

1.创建三个工程文件

如下图所示,我们创建好三个文件,分别是SeqList.c SeqList.h Test.c

SeqList.c用于顺序表的实现

SeqList.h用于顺序表的声明

Test.c用于测试顺序表

2.顺序表的概念

我们得先了解顺序表的概念,才能继续完成下去

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

顺序表一般可分为

静态顺序表:使用定长数组进行存储

动态顺序表:使用动态开辟的数组进行存储

3.顺序表的定义

我们先看静态顺序表是如何定义的,如下图所示,我们知道顺序表他也是用来存储数据的,既然是用来存储数据的,那么他必然要有一个数组来存储,然后还要有一个size来确定目前存储了一个数据。将这两个合并到一起就是一个结构体

 虽然说这可以当作一个静态顺序表来进行定义,但是要真是这样定义,还是会出现很多问题,比如说哪一天想要存储100个数据了,那么我们上面这个就是写死了,根本没法改。所以我们可以使用define来进行优化,如下图所示

这样的话,确实,解决了一些后续无法增加数据的问题,但是如果突然不想要整型类型了,他想要char类型的话,那这个顺序表又废了,所以我们还得再次进行优化,我们可以使用一个typedef来重定义类型,如下图所示

 当然这样其实还不够好,我们如果想要使用这个结构体的话,这个结构体类型太长了,我们写着写着都快烦死了。所以我们也可以对结构体进行typedef

如下图所示,我们让这个结构体类型变成了SL,当然这个有两种写法,一种是使用注释中的写法,另外一种就是在定义结构体的时候就typedef

最终代码如下(SeqList.h这个文件)

#pragma once

#define N 10
typedef int SQDateType;


typedef struct SeqList
{
	SQDateType arr[N];
	int size;
}SL;
//等价于typedef struct SeqList SL;

4.初始化顺序表

我们在说顺序表的概念的时候就提到过,顺序表是要实现增删查改四大功能的,但是在这之前,我们得先初始化顺序表

于是我们在头文件先进行一次初始化函数的声明

 在SeqList.c文件中,我们就要实现这个功能了,如下图所示,我们使用一个memset函数,在这里可能有些人还不熟悉或者不太了解这个函数,我们可以现场学习一下 ,如下图所示,他是将传入的一个指针,从他开始的前num个字节都设置为value

 所以下面中的意思就是将这个数组的全部元素设置为0,并且将size也就是目前的元素个数也设置为0

而对应这个函数也有他自己的头文件,我们为了方便,可以直接全部放在SeqList.h中

 既然如此,那么我们就开始来测试一下这个函数究竟对不对

 我们打完断点以后,直接使用F5,跳转至断点处,并打开调试的监视窗口,如下图所示,我们已经将顺序表给初始化完成了

 我们开始进入我们的函数,我们发现,这块并没有将这个顺序表给初始化啊。这是为什么呢?

 其实这块已经很多人发现了这个问题,因为我们传的其实是形参,形参的改变不会影响实参。我们就不该使用这个传值调用了,我们应该使用传址调用,我们现在将我们的代码都改为指针

 

 

而此时就能够完成我们的目标了,实现初始化顺序表

 顺序表初始化接口代码为

//顺序表初始化
void SeqListInit(SL* ps)
{
	memset(ps->arr, 0, sizeof(SQDateType) * N);
	ps->size = 0;
}

5.静态顺序表的尾插

在我们将顺序表给初始化以后,我们现在需要的就是试下顺序的表的增删查改,当然我们在讲述顺序表的概念的时候,提到了这两个关键点:

1.连续的物理存储地址------数组

2.数据必须是从头开始,依次存储------不能在数组的第一个元素插入一个,然后第二个又跑到了第三个元素上

那么我们就先来定义一下我们的接口函数,如下图所示,这里我们的命名与c++的标准库一致,让我们的程序更加规范

不过既然有尾插,那么与之对应的就有头插,尾删,以及头删,不妨我们也直接定义好他们的接口吧,如下图所示

那么我们先来实现尾插,如何实现尾插呢?我们可以试着画图理解一下,如下图所示,我们假设数组已经存储了5个元素了,此时他的size就是5,那么这个5刚好就是下一个数据的下标,所以我们就想到了,有了下标了,那不就是直接插入数据了吗。插入完之后再让size++就行了吗,确实是这样的。

我们来实现一下我们的想法,如下图所示

但是这样存在一个问题,如果顺序表满了呢?我们可以实验一下

我们进行调试,如下图所示,顺序表已经初始化完成

我们使用F10不进入函数内部进行调试,我们可以发现现在即将越界

此时已经越界了,我们发现arr[10]他与size进行同步变化,size直接变成了12,而不是变成了11,这个问题,在我们之前讲解调试的时候已经提到过了,这就是数组越界所带来的风险。size的数据已经被破坏了。所以这个顺序表已经废了

那么我们该怎么办呢?我们可以在顺序表满的时候提示一句顺序表满了,然后就直接返回,直接拦截这个错误的信息,不让他插入进去,所以实现如下

 这个时候我们再次调试一下,此时我们发现,拦截成功了。

 其实到这块我们也发现一个问题,那就是静态顺序表不太好,要么消耗的空间太大,要么空间不够。总之很麻烦。而我们一般下也不会去使用静态的顺序表,我们都是使用动态的顺序表,可以进行扩容的顺序表。

所以我们在这里就不在继续进行实现静态的顺序表的,我们转而实现动态的顺序表

三、顺序表的实现(升级为动态顺序表)

想要实现一个动态的顺序表,那么我们得先将我们的思路给理清晰,然后在我们的静态顺序表上进行修改

1.动态顺序表的定义

静态的顺序表是通过一个宏来进行确定一个数组的,既然是动态,那么我们就不能用宏了,我们可以使用一个指针,当然使用指针以后,我们就没法确定总容量了,所以我们还需要一个参数capacitiy称为容量

所以新的动态顺序表的定义就如下所示

 代码如下

typedef int SQDateType;


typedef struct SeqList
{
	SQDateType* a; //指向动态开辟的数组
	int size;	   //当前的有效数据个数
	int capacity;  //容量空间的大小
}SL;

2.动态顺序表的初始化

定义修改完后,我们就修改一下顺序表的初始化

因为a已经是一个指针了,所以说我们直接让a指向一个空指针就可以了。然后就让其他两个都变成0就行了。当然我们也可以一开始给他一块空间,当然这都无所谓了,因为我们可以在后面插入顺序表的时候就判断一下容量是否还有,如果没有容量,在那个时候在进行扩容即可

代码如下

//顺序表初始化
void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

3.动态顺序表的尾插

我们已经初始化好了,那么现在我们就来修改一下尾插

在静态顺序表的时候,如果满了,就拦截,但是在动态版的,我们就可以进行扩容了

下面是判断是否满了

 满了就得扩容,那么如何扩容呢?我们使用realloc函数,我们去查看他的信息

 当然如果我们看不懂也没有关系,打开有道字典,选择计算机,复制粘贴翻译即可

 他的意思就是,重新分配一个内存,因为我们的内存都是一块一块的断开的片段,所以我们就先看一看在他原来的地址上够不够我们之前的内存,如果够的化,那么就在原来的地址上原地扩容,如果不够,找一块连续的空间,将原来的数据都移动到这个新的空间上,最后将这个新的空间的地址返回,这里返回的void类型,所以需要进行强制类型转换。当然也有可能因为内存不够了,导致扩容失败。此时返回的就是NULL空指针

所以由上面的分析可以得到如下所示的代码,先对其进行扩容,然后如果内存不够扩容失败,则直接退出,如果扩容成功,则将这个地址给a这个指针,并让总容量扩大二倍,注意,我们一般习惯上扩大二倍的容量

 接下来我们就是扩容成功了,然后我们需要将这个数据给放进去,然后size++

 写到这一块,细心的人已经发现这里有一个bug了。当然没发现也没要紧。我们可以测试一下

为了方便测试,我们在这里先写出打印数据的接口,这个很简单,我们就直接写出来吧

 

  我们运行一下吧,我们发现程序挂了

这可不行,我们得调试一下,来看一看究竟是哪里错了,一开始的初始化是没有任何问题的

但是当我们下一步的时候,我们发现capacity的值居然是0。这说明这个函数内部出现问题了,于是我们知道了问题,就要进入这个函数里面去寻找问题

 在这一步的时候,我们发现了问题,因为我们一开始capacity是0,零乘以任何数都为0,所以程序肯定会出错

 所以为了避免这个错误,我们可以在定义一个变量,就可以完美的解决了

 此时我们的运行结果为,这样结果就跟我们预期一样了

 至此,我们的尾插就实现了

代码如下

//顺序表尾插
void SeqListPushBack(SL* ps, SQDateType x)
{
	//判断是否满了,如果满了,就得扩容了
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SQDateType* tmp = (SQDateType*)realloc(ps->a, newcapacity * sizeof(SQDateType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
	ps->a[ps->size] = x;
	ps->size++;
}

 当然我们也把打印函数也给出来

//打印数据
void SeqListPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
    printf("\n");
}

4.顺序表的头插

我们实现了尾插,但是有时候也需要往头插入数据,这个该如何实现呢?

我们的想法是这样的,从后往前,一个数据一个数据往后挪动即可,玩玩不可从前往后挪,因为这样会出问题的

所以基本逻辑的实现如下所示

 而对于这段代码,其实面临着和尾插一样的问题,就是空间不够了呢?所以我们需要增容,既然头插也要增容,尾插也要增容,那我们不妨将增容封装成一个函数吧,仅仅这两个函数使用,如下图所示

 然后我们就可以先测试一下我们的代码

 测试结果如下

 我们将这段代码给出

//扩容函数
void SeqListCheckCapacity(SL* ps)
{
	//判断是否满了,如果满了,就得扩容了
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SQDateType* tmp = (SQDateType*)realloc(ps->a, newcapacity * sizeof(SQDateType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
}
//顺序表尾插
void SeqListPushBack(SL* ps, SQDateType x)
{
	SeqListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}
//顺序表的头插
void SeqListPushFront(SL* ps, SQDateType x)
{
	SeqListCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}

 5.顺序表的尾删

尾部删除其实就比较简单了,只要size>0,他就可以进行删除,我们删除的思想是这样的,我们的数据都是依靠size进行管理的,所以我们只需要让size--就可以了,这样也就访问不到后面的数据了,当然我们判断size>0的时候可以使用一下暴力一点的方式。使用断言。

代码如下

//顺序表的尾删
void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;
}

测试数据如下

运行结果如下

 6.顺序表的头删

我们已经实现了顺序表的尾删,那么头删呢?其实头删跟头插是非常类似的,下图是我们的流程,从左往右走,让后面的数据覆盖前面的数据即可

 代码实现如下

//顺序表的头删
void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);
	int start = 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		start++;
	}
	ps->size--;
}

我们使用如下的测试用例

运行结果为

 7.顺序表任意位置的增加

 其实我们已经了解了顺序表的头插和尾插,那么就想能不能在任意位置都插入一个数据呢,或者任意位置的删除呢?我们应该也是可以实现的,所以我们现在来实现一下任意位置的插入和删除。我们先定义好这两个的函数声明

 我们先来实现任意位置的插入

任意位置的插入其实和头插是极其相似的,只不过结束点从0变成了pos

 代码实现如下

//任意位置的插入
void SeqListInsert(SL* ps, int pos, SQDateType x)
{
	assert(pos < ps->size);
	SeqListCheckCapacity(ps);
	int end = ps->size - 1;
	while (pos <= end)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

这样的话,我们给一组测试用例

 运行结果为

8.顺序表任意位置的删除

我们接下来来实现一下任意位置的删除,其实这个跟头删也是极其相似的,只不过我们将结束条件变成了pos控制的而已

代码如下

//任意位置的删除
void SeqListEarse(SL* ps, int pos)
{
	assert(pos < ps->size);
	int start = pos + 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		start++;
	}
	ps->size--;
}

 我们的测试用例如下

 运行结果为

 9.顺序表的销毁

我们最后还需要加上一个销毁顺序表的函数,因为我们的空间都是malloc出来的,必须要还回去,否则会发生内存泄漏

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

10.顺序表的查找

增删查改,我们现在就来实现查找

我们先声明好这个函数

然后我们来实现他,实现它也很简单,就是遍历一边他知道找到这个元素,找不到返回-1,找到返回它的下标

代码实现如下

//顺序表的查找
int SeqListFind(SL* ps, SQDateType x)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

测试用例如下

 运行结果为

 11.顺序表的修改

 接下来就来实现顺序表的修改吧

这是顺序表修改的声明

 代码如下

//顺序表的修改
void SeqListModity(SL* ps, int pos, SQDateType x)
{
	assert(pos < ps->size);
	ps->a[pos] = x;
}

测试用例

运行结果为

 12.顺序表的菜单

现在,我们已经将一个顺序表的大致功能给解决了,我们接下来就来写一个菜单,将这些功能给整合起来。

菜单很好写,这里就直接给出代码了

void meau()
{
	printf("***************************************\n");
	printf("****     请输入你想要执行的操作    ****\n");
	printf("****     1.头插                    ****\n");
	printf("****     2.尾插                    ****\n");
	printf("****     3.头删                    ****\n");
	printf("****     4.尾删                    ****\n");
	printf("****     5.任意位置添加            ****\n");
	printf("****     6.任意位置删除            ****\n");
	printf("****     7.查找数据                ****\n");
	printf("****     8.修改数据                ****\n");
	printf("****     9.顺序表置零              ****\n");
	printf("****     10.打印顺序表             ****\n");
	printf("****     0.退出顺序表              ****\n");
	printf("***************************************\n");
	printf("请输入>:\n");
}
void test()
{
	int x = 0;
	int pos = 0;
	SL s;
	SeqListInit(&s);
	int input = 0;
	do
	{
		meau();
		scanf("%d", &input);
		switch (input)
		{
			case 1:
				printf("请输入你头插入的数据:\n");
				scanf("%d", &x);
				SeqListPushFront(&s, x);
				break;
			case 2 :
				printf("请输入你尾插入的数据:\n");
				scanf("%d", &x);
				SeqListPushBack(&s, x);
				break;
			case 3:
				printf("执行头删\n");
				SeqListPopFront(&s);
				break;
			case 4:
				printf("执行尾删\n");
				SeqListPopBack(&s);
				break;
			case 5:
				printf("请输入你需要插入的数据:\n");
				scanf("%d", &x);
				printf("请输入你需要插入的位置(下标从零开始):\n");
				scanf("%d", &pos);
				SeqListInsert(&s, pos, x);
				break;
			case 6:
				printf("请输入你需要删除的数据下标(下标从零开始):\n");
				scanf("%d", &pos);
				SeqListErase(&s, pos);
				break;
			case 7:
				printf("请输入你需要查找的数据:\n");
				scanf("%d", &x);
				int ret = SeqListFind(&s, x);
				printf("该数据的下标是:%d\n", ret);
				printf("如果返回值是-1,说明没找到\n");
				break;
			case 8:
				printf("请输入需要修改的下标(下标从零开始):\n");
				scanf("%d", &pos);
				printf("请输入修改后的数据:\n");
				scanf("%d", &x);
				SeqListModity(&s, pos, x);
				break;
			case 9:
				SeqListInit(&s);
				printf("顺序表已经成功置零了\n");
				break;
			case 10:
				printf("顺序表目前的数据为:\n");
				SeqListPrint(&s);
				break;
			case 0:
				printf("即将退出程序,感谢您的使用\n");
				break;
			default:
				printf("输入数据有误,请重新输入!\n");
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

 三、顺序表完整代码

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void meau()
{
	printf("***************************************\n");
	printf("****     请输入你想要执行的操作    ****\n");
	printf("****     1.头插                    ****\n");
	printf("****     2.尾插                    ****\n");
	printf("****     3.头删                    ****\n");
	printf("****     4.尾删                    ****\n");
	printf("****     5.任意位置添加            ****\n");
	printf("****     6.任意位置删除            ****\n");
	printf("****     7.查找数据                ****\n");
	printf("****     8.修改数据                ****\n");
	printf("****     9.顺序表置零              ****\n");
	printf("****     10.打印顺序表             ****\n");
	printf("****     0.退出顺序表              ****\n");
	printf("***************************************\n");
	printf("请输入>:\n");
}
void test()
{
	int x = 0;
	int pos = 0;
	SL s;
	SeqListInit(&s);
	int input = 0;
	do
	{
		meau();
		scanf("%d", &input);
		switch (input)
		{
			case 1:
				printf("请输入你头插入的数据:\n");
				scanf("%d", &x);
				SeqListPushFront(&s, x);
				break;
			case 2 :
				printf("请输入你尾插入的数据:\n");
				scanf("%d", &x);
				SeqListPushBack(&s, x);
				break;
			case 3:
				printf("执行头删\n");
				SeqListPopFront(&s);
				break;
			case 4:
				printf("执行尾删\n");
				SeqListPopBack(&s);
				break;
			case 5:
				printf("请输入你需要插入的数据:\n");
				scanf("%d", &x);
				printf("请输入你需要插入的位置(下标从零开始):\n");
				scanf("%d", &pos);
				SeqListInsert(&s, pos, x);
				break;
			case 6:
				printf("请输入你需要删除的数据下标(下标从零开始):\n");
				scanf("%d", &pos);
				SeqListErase(&s, pos);
				break;
			case 7:
				printf("请输入你需要查找的数据:\n");
				scanf("%d", &x);
				int ret = SeqListFind(&s, x);
				printf("该数据的下标是:%d\n", ret);
				printf("如果返回值是-1,说明没找到\n");
				break;
			case 8:
				printf("请输入需要修改的下标(下标从零开始):\n");
				scanf("%d", &pos);
				printf("请输入修改后的数据:\n");
				scanf("%d", &x);
				SeqListModity(&s, pos, x);
				break;
			case 9:
				SeqListInit(&s);
				printf("顺序表已经成功置零了\n");
				break;
			case 10:
				printf("顺序表目前的数据为:\n");
				SeqListPrint(&s);
				break;
			case 0:
				printf("即将退出程序,感谢您的使用\n");
				break;
			default:
				printf("输入数据有误,请重新输入!\n");
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

SeqList.h文件

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





//以下是动态的顺序表

typedef int SQDateType;


typedef struct SeqList
{
	SQDateType* a; //指向动态开辟的数组
	int size;	   //当前的有效数据个数
	int capacity;  //容量空间的大小
}SL;
//等价于typedef struct SeqList SL;

//增删查改四大功能的函数接口声明
//初始化
void SeqListInit(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SQDateType x);
//头插
void SeqListPushFront(SL* ps, SQDateType x);
//尾删
void SeqListPopBack(SL* ps);
//头删
void SeqListPopFront(SL* ps);
//打印
void SeqListPrint(SL* ps);
//任意位置的插入
void SeqListInsert(SL* ps, int pos, SQDateType x);
//任意位置的删除
void SeqListErase(SL* ps, int pos);
//销毁顺序表
void SeqListDestory(SL* ps);
//顺序表的查找
int SeqListFind(SL* ps, SQDateType x);
//顺序表的修改
void SeqListModity(SL* ps, int pos, SQDateType x);


SeqList.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"



//以下是动态的顺序表
//顺序表初始化
void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//打印数据
void SeqListPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
//顺序表的销毁
void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}
//扩容函数
void SeqListCheckCapacity(SL* ps)
{
	//判断是否满了,如果满了,就得扩容了
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SQDateType* tmp = (SQDateType*)realloc(ps->a, newcapacity * sizeof(SQDateType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
}
//顺序表尾插
void SeqListPushBack(SL* ps, SQDateType x)
{
	SeqListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}
//顺序表的头插
void SeqListPushFront(SL* ps, SQDateType x)
{
	SeqListCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}
//顺序表的尾删
void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;
}
//顺序表的头删
void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);
	int start = 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		start++;
	}
	ps->size--;
}
//任意位置的插入
void SeqListInsert(SL* ps, int pos, SQDateType x)
{
	assert(pos < ps->size);
	SeqListCheckCapacity(ps);
	int end = ps->size - 1;
	while (pos <= end)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}
//任意位置的删除
void SeqListErase(SL* ps, int pos)
{
	assert(pos < ps->size);
	int start = pos + 1;
	while (start < ps->size)
	{
		ps->a[start - 1] = ps->a[start];
		start++;
	}
	ps->size--;
}
//顺序表的查找
int SeqListFind(SL* ps, SQDateType x)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}
//顺序表的修改
void SeqListModity(SL* ps, int pos, SQDateType x)
{
	assert(pos < ps->size);
	ps->a[pos] = x;
}


 

总结

好了,本小节就讲解了顺序表的实现,难度可能要比之前c语言要大很多,不过不用担心,只要认真学,一定是可以学会的。加油!,如果对你有帮助的话,那么不要忘记点赞加收藏哦!!!

想看更多精彩内容,那么就赶快来关注我吧!!!

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

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

相关文章

艾美捷NCTC-135培养基化学性质和基本配方

艾美捷NCTC-135培养基背景&#xff1a; NCTC培养基&#xff0c;由马里兰州贝塞斯达国家癌症研究所&#xff08;NCI&#xff09;生物实验室组织培养科开发&#xff0c;用于建立和维持L929小鼠细胞株。 艾美捷NCTC-135培养基化学性质&#xff1a; 外观&#xff1a;白色至浅粉色…

[附源码]Python计算机毕业设计Django超市商品管理

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Android -- 每日一问:谈谈MVC、MVP和MVVM模式,你有在自己的项目中使用过吗?

经典回答 MVC 模式 全名是Model–View–Controller&#xff0c;是模型(model)&#xff0d;视图(view)&#xff0d;控制器(controller)的缩写&#xff0c;一种软件设计典范&#xff0c;用一种业务逻辑、数据、界面显示分离的方法组织代码&#xff0c;在改进和个性化定制界面及用…

[附源码]Python计算机毕业设计SSM基于的高速收费系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

防火墙双机热备配置实验

目录 一、实验拓扑 二、配置云 三、配置防火墙 四、分配FW的接口地址与安全区域 五、按图示进行配置 六、双机热备的配置 七、配置NAT 八、模拟双机热备的切换 一、实验拓扑 看上去挺复杂的其实这个实验还是比较简单的&#xff0c;Client1配置为IP 10.3.0.10 网关10.3.…

python教程十二 字典

字典 字典是另一种可变容器模型&#xff0c;且可存储任意类型对象。 字典的每个键值 key>value 对用冒号 : 分割&#xff0c;每个对之间用逗号(,)分割&#xff0c;整个字典包括在花括号 {} 中 ,格式如下所示&#xff1a; d {key1 : value1, key2 : value2, key3 : value3…

学会模态计算,你就掌握了结构振动冲击计算的核心

模态计算对于认识结构振动特性至关重要&#xff0c;通过模态计算可以得到模态的固有频率&#xff0c;振型&#xff0c;参与系数和有效质量等参数&#xff0c;模态计算的这些参数我们应该很熟悉&#xff0c;但是如果正确合理的使用这些结果指导工程计算&#xff0c;是我们今天讨…

[附源码]Python计算机毕业设计滁州市围棋协会Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

12月12日: 学习跟着猫叔写代码

视频地址&#xff1a;fastadmin系列教程:小白学习之路 学前准备 安装过程 数据库分析 关联查询搜索 数据校验 视图渲染 api登录注册 token验证 table表格_哔哩哔哩_bilibili 前两节是安装fastadmin操作&#xff08;可参考我自己的文章&#xff09; 11月30日&#xff1a;linux服…

当要测试的对象依赖另一个无法控制的对象(系统相关、第三方服务等),这个时候我们应该如何测试?

一.问题描述 判断文件是否有效的需求变更了&#xff1a;有效的文件扩展名存储在文件系统中&#xff0c;要测试的FileVerify类就依赖FileExtensionManager类&#xff0c;在这种场景下如何测试FileVerify类的逻辑呢? 1 public class FileVerify2 { 3 …

精品基于SSM的社区疫情防控平台

《基于SSM的社区疫情防控平台》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 使用技术&#xff1a; 开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&…

(附源码)springboot螺丝加工厂订单管理 毕业设计 010346

题 目 springboot螺丝加工厂订单管理 目 录 摘要 1 1 绪论 1 1.1项目开发的背景 1 1.2项目开发的意义 1 1.3系统开发技术的特色 1 1.4论文结构与章节安排 1 2 螺丝加工厂订单管理 系统分析 3 2.1 可行性分析 3 2.2 系统流程分析 3 2.2.1数据流程 3 2.3.2业务流程 4 2.3 系统…

C++11标准模板(STL)- 算法(std::sort_heap)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 数据结构的堆物理结构是数…

百度地图(HTML5新特性)-全面详解(学习总结---从入门到深化)

目录 百度地图_账号和获取密钥 百度地图_初始化 百度地图_变更地图类型 百度地图_添加控件 百度地图_改变控件位置 百度地图_添加覆盖物 百度地图_自定义标注图标 百度地图_添加文本标注 百度地图_正/逆地址解析 百度地图_信息窗口 百度地图_规划驾车路线 百度地图_…

亚马逊、速卖通、阿里国际自动和手动广告的核心是什么?自己养买家号测评的好处

亚马逊等跨境电商平台在打造的新品期&#xff0c;因为选择的细分类目是非常精准刚需的&#xff0c;词少&#xff0c;所以一开始只开启了自动广告&#xff0c;自动广告跑起来&#xff0c;转化很好。 自动广告跑了一段时间之后&#xff0c;把自动广告里表现比较好的出单词都挑出…

冰雪旅游热开启!IU酒店与您畅游山水之间

连日来&#xff0c;全国多地不断调整疫情防控措施&#xff0c;提高科学精准防控能力。国家防疫“新十条”出台后&#xff0c;大众旅游热情明显增高。 据穷游网站内数据显示&#xff0c;去海南、云南等地避寒&#xff0c;或前往东北、新疆等地滑雪备受用户推崇。三亚、上海、成…

spark上传文件和追加文件到hdfs

val status uploadFile(“C:\Users\com\Desktop\测试数据\”,“/test/file/”,“报销单.docx”) if(status) println(“上传成功&#xff01;”) else println(“上传失败”) } /** 本地文件上传到 hdfs param localDirectory 本地目录 param hdfsDirectory hdfs目录 pa…

胰岛素海藻酸钠纳米粒(INS-SA-NP)|葡聚糖(Dextran)修饰Fe304纳米颗粒

胰岛素海藻酸钠纳米粒&#xff08;INS-SA-NP&#xff09;|葡聚糖(Dextran)修饰Fe304纳米颗粒 中文名称&#xff1a;胰岛素海藻酸钠纳米粒 英文名称&#xff1a;INS-SA-NP 纯度&#xff1a;95% 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 外观:固体或粘性液…

flutter系列之:如丝般顺滑的SliverAppBar

文章目录简介SliverAppBar详解SliverAppBar的使用总结简介 对于一个APP来说&#xff0c;肯定会有一个AppBar&#xff0c;这个AppBar一般包含了APP的导航信息等。虽然我们可以用一个固定的组件来做为AppBar&#xff0c;但是这样就会丢失很多特效&#xff0c;比如将AppBar固定在…

Java基础 二维数组简介

一、二维数组的定义 当一维数组元素的类型也是一维数组时&#xff0c;便构成了“数组的数组”&#xff0c;即二维数组。二维数组定义的一般格式&#xff1a; dataType arrayName[length1][length2];其中&#xff0c; dataType 为数据类型&#xff0c; arrayName 为数组名&…