数据结构之顺序表_动态顺序表(C语言版)

静态顺序表我们已经实现完毕了,下来我们实现一下动态顺序表

静态链接:数据结构之顺序表——静态顺序表(C语言版)
首先来了解一下两个顺序表的差别
一、内存管理的灵活性
动态分配与释放:动态顺序表能够在运行时根据需要动态地分配和释放内存空间。这意味着,当数据量增加时,它可以自动扩容以容纳更多的数据;而当数据量减少时,理论上也可以相应地释放不再需要的内存空间(尽管这通常需要程序员手动操作或依赖垃圾回收机制,具体取决于编程语言)。这种灵活性使得动态顺序表能够更高效地管理内存资源。
避免内存浪费:与静态顺序表相比,动态顺序表能够更准确地根据实际需求分配内存空间,从而避免了因预先分配过多内存而导致的内存浪费问题。同时,它也能够在数据量减少时释放部分内存空间,进一步提高了内存资源的利用率。
二、操作的便捷性
插入与删除操作的灵活性:在动态顺序表中,插入和删除操作可以更加灵活地进行。由于内存空间是动态分配的,因此可以在不移动大量元素的情况下完成插入和删除操作(尽管在某些情况下仍然需要移动部分元素以保持数据的连续性)。相比之下,静态顺序表在进行插入和删除操作时通常需要移动大量的元素,这降低了操作的效率。
适应数据变化的能力:动态顺序表能够更好地适应数据量的变化。当数据量增加时,它可以自动扩容以容纳更多的数据;而当数据量减少时,它也可以相应地调整内存空间的大小。这种能力使得动态顺序表在处理不确定大小的数据集时更加高效和便捷

总而言之,就是为了使我们的顺序表更加灵活,长度不够去动态开辟。
下来我们通过代码来实现一下动态顺序表。
首先还是一样,我们从头文件开始写起

#pragma once
//包含头文件
#include
#include
#include
// 定义顺序表存储的数据类型 
typedef int SQDataType;
// 定义顺序表的结构体  
typedef struct {
   
	SQDataType* arr;// 指向动态分配数组的指针(数组的首地址)  
	int size; // 顺序表当前存储的元素个数(有效长度)
	int capacity; // 顺序表的容量(即数组的总大小)  
}SL;
void SListInIt(SL* ps);//初始化函数

为了方便测试,我们完成打印函数

void PrintSList(SL* ps)
{
   
	for (int i = 0; i < ps->size; i++)
	{
   
		printf("%d  ", ps->arr[i]);
	}
	printf("\n");
}

下来我们完成初始化函数:

//包含我们自己写的头文件
#include"SList_02.h"
// 初始化顺序表  
// 为顺序表分配初始内存,并设置size为0,capacity为指定的初始容量  
void SListInIt(SL* ps)
{
   
	ps->arr = NULL;//将数组的首地址赋值为空
	ps->size = 0;//数组的有效长度
	ps->capacity = 0;//容量
}

OK,经过调试我们知道我们的初始化已经完成了
数据结构之顺序表_动态顺序表(C语言版)_第1张图片
下来我们写尾插函数

void SListPushback(SL* ps,SQDataType x)
{
   
	//首先进行动态内存分配malloc
	int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
	if (ps->capacity == ps->size)
	{
   
		SQDataType* temp = malloc(newcapacity * sizeof(SQDataType));
		if (temp == NULL)
		{
   
			printf("erro\n");
			exit(-1);
		}
		else
		{
   
			ps->arr = temp;
			ps->capacity = newcapacity;
		}
	}
	ps->arr[ps->size] = x;
	ps->size++;
}

运行一下
数据结构之顺序表_动态顺序表(C语言版)_第2张图片
尾插成功
由于我们每次都需要检查一下剩余的空间是否足够所以我们这里写一个检查函数,就会方便很多

void SqListCheck(SL* ps)
{
   
	int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;//创建一个变量newcapacity,如果原来的容量为0则修改为4,如果不为0,则为原来的二倍
	if (ps->capacity == ps->size)//说明容量满了,需要扩容了
	{
   
		SQDataType *tmp=realloc(ps->arr, newcapacity * sizeof(SQDataType));//扩容二倍
		//如果扩容失败
		if (tmp == NULL)
		{
   
			printf("error\n");
			exit(-1);//非正常退出程序
		}
		//正常执行
		else
		{
   
			ps->arr = tmp;//扩容的新地址给原来的变量
			ps->capacity = newcapacity;//新容量赋值给原来的容量
		}
	}
}

头插函数

void SListPushFront(SL* ps, SQDataType x)
{
   
	//程序开始先检查一下需不需要扩容
	SqListCheck(ps);//ps已经是指针变量了指向SL类型
	//头插就是把所有的数据往后挪动一位,空出来索引为0的位置,将新数据插入进去
	int end = ps->size - 1;//由于我们每次插入数据之后,size都会++所以这里end表示的是索引值
	while (end >= 0)
	{
   
		ps->arr[end + 1] = ps->arr[end]

你可能感兴趣的:(数据结构,数据结构,c语言,算法)