数据结构(1)--顺序表

这是写给自己以后复习看的,把重要的记下来

目前我已经学完了栈和队列,对数据结构已经有了一定的理解,相比于C语言,我认为数据结构其实没有"新知识",它的真面目是运用C语言学的,数组,函数,指针,结构体,动态内存管理等知识来做一些结构,从而更好地解决一些问题。

一.什么是顺序表?

所谓顺序表,有点像数组,但不完全是

**定义:**一段物理地址连续的存储单元,依次存储数据的线性结构。

二.核心特征

特征就很符合线性规律:

  1. 物理连续:内存地址相邻,无空隙。

  2. 逻辑有序:存储顺序与逻辑顺序一致。

不论是物理上还是逻辑上,顺序表都是线性的。

顺序表也分为动态顺序表和静态顺序表,通常都是用动态,因为静态顺序表申请的空间是固定的,不能扩容,申请空间小了会溢出,申请多了又会浪费空间。

三.基本结构

复制代码
//动态顺序表
typedef struct SeqList 
{
	SLDataType* arr;//动态数组,用于储存数据
	int size;//用来表示顺序表长度
	int capacity;//空间大小
}SL;

基本结构就长这样了,其中的SLDataType是方便改数据类型的。

接下来就是重头戏了。

四.关于顺序表的操作

复制代码
void SLInit(SL*ps);//顺序表初始化

void SLDestroy(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);//顺序表指定位置删除

我写了这么多操作,说实话刚开始学还是有点痛苦的,有点懵逼,不过现在好多了。

一个个来介绍吗?我把对应的代写出来吧。

1.初始化

cpp 复制代码
void SLInit(SL* ps)//初始化
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

很简单,没啥好说的。

2.销毁

cpp 复制代码
void SLDestroy(SL* ps)//销毁
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

简单来说就是该置零的置零,该置空的置空。

3.尾插

cpp 复制代码
void SLpushback(SL* ps, SLDataType x)//尾插
{
	
		assert(ps);//检查空指针
	
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* temp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->arr = temp;
		ps->capacity = newcapacity;
		
	}
ps->arr[ps->size++] = x;
}

尾插是我感觉最难的步骤了,这个解决了就好理解多了。

我们先看最后一句:

cpp 复制代码
ps->arr[ps->size++] = x;

这其实才是插入,前面的部分是检查容量外加扩容。这一步是先插入,再让size++;

重点是扩容部分。

cpp 复制代码
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;

这一步是判断初始容量,如果为0,就直接让新空间==4,如果不是0,那就2倍扩容(当然前提是if的条件------ps->size == ps->capacity)

cpp 复制代码
SLDataType* temp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
if (temp == NULL)
{
	perror("realloc fail");
	return;
}
ps->arr = temp;
ps->capacity = newcapacity;

切记,刚才那个步骤只是改变了capacity的值,并没有实际开辟新空间,这一步就是配合newcapacity 来扩容arr的,这样就好理解了。

这样我们就知道了,尾插就是就是 容量检查(扩容)+插入(size++)

这样就可以把前面那和检查扩容部分单独写成一个函数:

cpp 复制代码
void  SLCheckCapacity(SL*ps)
{
	assert(ps);

	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* temp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->arr = temp;
		ps->capacity = newcapacity;

	}
}

这样代码就可以简化了,比如接下来的头插:

cpp 复制代码
void SLpushfront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	SLCheckCapacity(ps);//检查扩容部分写成函数
	for (int i = ps->size;i > 0;i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

头插这个循环开始可能会很绕,其实我现在看到都觉得绕了点,它是让数据一个个后移,比如

arr4=arr3,arr3=arr2......arr1=arr0;

不太好讲,稍微想一下就知道在后移动了,这样吧arr0空出来,就可以插入进去了。

记住让size++.

4.尾删

cpp 复制代码
void SLpopback(SL*ps)//尾删
{
	assert(ps);
	assert(ps->size);
	--ps->size;
}

很简单,没啥好说的

5.头删

cpp 复制代码
void SLpopfront(SL* ps)//头删
{
	assert(ps);
	assert(ps->size);
	for (int i = 0;i<ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

头删也简单,细想一下就明白了。

6.指定位置插入

cpp 复制代码
void SLInsert(SL* ps, int pos, SLDataType x)//指定位置插入
{
	SLCheckCapacity(ps);
	assert(pos >= 0 && pos <= ps->size);
	for (int i = ps->size;i > pos;i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

通过循环把数据往后移动,让pos空出来,从而插入数据。

7.指定位置删除

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

比较简单,还行。

好了,总共就这样了,以后复习应该很容易看懂了

相关推荐
额鹅恶饿呃2 小时前
C语言中的数据结构和变量
c语言·数据结构·算法
MartinYeung52 小时前
[论文学习]大语言模型安全综述:攻击、防御、对齐、度量与护栏的深度解析
学习·安全·语言模型
AOwhisky3 小时前
Python 学习笔记(第三期)——流程控制:条件判断与循环结构
运维·笔记·python·学习·云原生·流程控制·循环
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:白噪音场景的视觉设计
学习·flutter·华为·harmonyos
万法若空3 小时前
【数据结构-哈希表】哈希表原理
数据结构·算法·散列表
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:呼吸练习的完整生命周期
学习·flutter·华为·harmonyos
Zeeland3 小时前
构建护城河:自学习 Agent
学习
尼米棕熊3 小时前
大模型学习8上-推理部署框架llama.cpp与Ollama使用指北
学习·llama
tachibana24 小时前
hot100 翻转二叉树(226)
java·数据结构·算法·leetcode
brave_zhao4 小时前
nginx的进程架构
java·学习·nginx