C语言手撕顺序表

目录

一、概念

1、静态顺序表:使用定长数组存储元素。

2、动态顺序表:使用动态开辟的数组存储

二、接口实现

1、对顺序表的初始化

2、对数据的销毁

3、对数据的打印

4、检查是否需要扩容

5、尾插

6、头插

7、尾删

8、头删

9、在pos位置插入x

10、在pos位置处删除x

心得:


一、概念

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

顺序表一般分为

1、静态顺序表:使用定长数组存储元素。

2、动态顺序表:使用动态开辟的数组存储

我们一般使用动态顺序表,因为静态顺序表的数组大小固定的,而动态可以根据我们需求的不同去在线扩容,所以接下来的文章围绕如何实现动态顺序表来讲解。

二、接口实现

对数据结构我们一般采用增删查改去实现。

cpp 复制代码
#pragma once

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

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;//存储有效数据的大小
	int capacity;//空间大小
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);//尾插
void SeqListPushFront(SeqList* ps, SLDateType x);//头插
void SeqListPopFront(SeqList* ps);//头删
void SeqListPopBack(SeqList* ps);//尾删
void SeqListCheckCapacity(SeqList* ps);//检查是否需要扩容
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
//修改特定位置的值
void SeqListModify(SeqList* ps, int pos,int value);

1、对顺序表的初始化

cpp 复制代码
void SeqListInit(SeqList* ps)
{
	ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 4);
	if (ps->a == NULL)//需要检查动态开辟内存是否开辟成功
	{
		perror(malloc);
		exit(-1);//直接程序退出,因为空间都开辟失败,后面没法写
	}
	ps->size = 0;
	ps->capacity = 4;
}

2、对数据的销毁

因为我们是动态开辟的内存,最后肯定是需要free释放。

cpp 复制代码
void SeqListDestroy(SeqList* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

3、对数据的打印

因为我们时刻要检查每一部分代码的正确性,需要数据检验,所以需要专门一个打印函数

cpp 复制代码
void SeqListPrint(SeqList* ps)
{
	for (int i=0;i<ps->size;i++)
	{
		printf("%d ", ps->a[i]);
	}
}

4、检查是否需要扩容

因为动态内存,每当我们插入新的数据时,总需要将存储有效数据的大小增加,当我们开辟的空间不够时,就需要扩容,利用realloc函数的性质。

cpp 复制代码
void SeqListCheckCapacity(SeqList* ps)
{
	if (ps->size == ps->capacity)
	{
		SLDateType* tmp = (SLDateType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDateType));
		//注意动态内存开辟的单位都是字节
		if (tmp == NULL)
		{
			perror(realloc);
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
}

5、尾插

cpp 复制代码
void SeqListPushBack(SeqList* ps, SLDateType x)
{
	//先考虑空间大小够不够,需不需要扩容
	SeqListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

6、头插

头插还需要用memmove函数去挪动数据

cpp 复制代码
void SeqListPushFront(SeqList* ps, SLDateType x)
{
	//也需要考虑扩容的问题
	SeqListCheckCapacity(ps);
	memmove(ps->a + 1, ps->a, ps->size*sizeof(SLDateType));
	ps->size++;
	ps->a[0] = x;
}

7、尾删

我们需要检查size是否已经小于0,防止数组的越界,一般用assert去暴力的检查

cpp 复制代码
void SeqListPopBack(SeqList* ps)
{
	assert(ps->size > 0);//暴力的检查
	/*if (ps->size == 0)
		return;*/
	//温柔的检查
	ps->size--;
}

8、头删

cpp 复制代码
void SeqListPopFront(SeqList* ps)
{
	assert(ps->size > 0);
	memmove(ps->a, ps->a + 1, ps->size* sizeof(SLDateType));
	ps->size--;
}

9、在pos位置插入x

cpp 复制代码
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	SeqListCheckCapacity(ps);
	assert(pos >= 0 && pos < ps->size);
	memmove(ps->a+pos + 1, ps->a+pos, sizeof(SLDateType)*(ps->size-pos));
	ps->a[pos] = x;
	ps->size++;
}

10、在pos位置处删除x

cpp 复制代码
void SeqListErase(SeqList* ps, int pos)
{
	assert(ps->size > 0);
	memmove(ps->a + pos, ps->a + pos + 1,sizeof(SLDateType)*(ps->size-pos-1));
	ps->size--;
}   

心得:

顺序表开启了数据结构的的序章,顺序表算是很简单的数据结构了,从此我们需要敲一部分代码,编译一次,不能一股脑的输出,结果编译发现好多个bug,需要写一部分,编译一部分,这样才更加的有持续性。

相关推荐
墨楠。33 分钟前
数据结构学习记录-树和二叉树
数据结构·学习·算法
Aqua Cheng.1 小时前
MarsCode青训营打卡Day10(2025年1月23日)|稀土掘金-147.寻找独一无二的糖葫芦串、119.游戏队友搜索
java·数据结构·算法
qy发大财1 小时前
平衡二叉树(力扣110)
数据结构·算法·leetcode·职场和发展
佳心饼干-1 小时前
数据结构-栈
开发语言·数据结构
我们的五年1 小时前
【C语言学习】:C语言补充:转义字符,<<,>>操作符,IDE
c语言·开发语言·后端·学习
siy23332 小时前
【c语言日寄】Vs调试——新手向
c语言·开发语言·学习·算法
黄交大彭于晏2 小时前
C语言常用知识结构深入学习
c语言·学习·word
可涵不会debug3 小时前
C语言文件操作:标准库与系统调用实践
linux·服务器·c语言·开发语言·c++
自由自在的小Bird3 小时前
简单排序算法
数据结构·算法·排序算法
利刃大大4 小时前
【Linux入门】2w字详解yum、vim、gcc/g++、gdb、makefile以及进度条小程序
linux·c语言·vim·makefile·gdb·gcc