【数据结构】初识数据结构01——顺序表

发布于:2022-11-08 ⋅ 阅读:(469) ⋅ 点赞:(0)

目录

写在开头:不积硅步,无以至千里

顺序表的结构

顺序表的数据存储

malloc:

realloc:

自定义顺序表的成员

顺序表的初始化

顺序表的增删查改

检查容量

插入(增):

删除(删):

查找(查):

更改(改):

小结


顺序表的结构

顺序表的数据存储

顺序表之所以被称为顺序表,就是因为顺序表所开辟的内存空间连续的,因为要开辟一段连续的内存空间,所以我们很自然的想到使用内存函数来开辟这段内存。

我们先来回顾本次会使用到的两个内存函数:mallocrealloc


malloc:

声明:

void *malloc( size_t size );

参数:size是需要开辟的字节数

返回值:返回一个指针,指向开辟的内存空间;如果开辟失败,则返回一个空指针


realloc:

声明:

void *realloc( void *memblock, size_t size );

参数:

  1. memblock指向需要重新分配内存的空间
  2. size是需要重新分配给这块空间的字节数

返回值:返回一个指针,指向重新分配内存的空间


自定义顺序表的成员

我们已经知道,顺序表的数据要存储到一块连续的空间,而这块空间是我们动态开辟出来的,所以在我们的顺序表成员变量中,我们需要一个指针来接收这块空间的起始位置,同时,我们需要一个变量来记录目前占用的个数,需要另外一个变量记录顺序表一共开辟了多少数量。

typedef int SLDataType;
struct SeqList
{
	SLDataType* a;
	int size;
	int capacity	
};

*备注::这里我们将int重定义为SLDataType是为了方便以后修改其他数据

为了方便,我们将我们自定义的结构体重新定义为SL,并创建一个SL类型的变量s1

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity
}SL;

SL s1;

顺序表的初始化

完成上面的操作后,我们需要初始化一下我们的顺序表,我们通过一个简单的函数实现了初始化

#include <stdio.h>
void SLInit(SL* ps)
{
	ps->a = NULL;//使用NULL记得引头文件哦
	ps->size = 0;
	ps->capacity;
}

顺序表的增删查改

检查容量

在进行增删查改操作之前,我们的s1中的a还没有指向任何空间,因为在后期很多操作中我们都会检查容量是否已满并考虑扩容,因此我们封装一个函数来检查当前容量,如果不够就扩容

void SLCheckcapacity(SL* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps, newcapacity *sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("malloc fail::::");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

插入(增):

声明:

void SLInsert(SL* ps, int pos, SLDataType x);

变量:

  1. ps是SL*类型的指针,指向动态开辟的空间
  2. pos是要插入的位置,从0开始
  3. x是要插入的数值(SLDataType类型)

思路

 我们要在pos位置插入,就要把pos后面的全部向后挪走

 


 首先我们记住最后一个元素的下标

void SLInsert(SL* ps, int pos, SLDataType x)
{
	int end = ps->size - 1;
}

接下来将end指向的元素挪动到end-1的位置处,执行完后我们让end向左移动一下,直到end小于pos

void SLInsert(SL* ps, int pos, SLDataType x)
{
	SLCheckcapacity(ps);//别忘了检查容量哦
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end+1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}


删除(删):

声明:

void SLErase(SL* ps, int pos);

参数:

  1. ps是一个SL*类型的指针,指向开辟的空间
  2. pos是要删除的位置下标

思路:

将要删除的位置用后面的数据覆盖掉, 因此我们定义一个begin变量,让begin位置的数据放到begin的前一个位置,当begin<size的时候就停止

 


 


void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos!=0);
	int begin = pos + 1;
	while (begin<ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;

}

查找(查):

声明:

int SLFind(SL* ps,SLDataType x,int begin);

参数:

ps是指向开辟空间的指针

x是要查找的数据

begin是开始查找的位置

由于查找的本身逻辑很简单,在这里我只贴上代码,供大家参考

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

更改(改):

声明:

void SLRevise(SL* ps, SLDataType x, int pos);

参数:

  1. ps是指向开辟空间的指针
  2. pos是要修改的位置
  3. x是要修改的数值
void SLRevise(SL* ps, SLDataType x, int pos)
{
	ps->a[pos] = x;
}

小结

如果你能坚持看到这里,相信你一定对顺序表有了一定的了解,请不要吝啬为笔者点赞,这是我更新的动力,锲而不舍,金石可镂,没有付出不会得到回报,最后,为努力学习知识的你点赞!

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到