c语言实现动态顺序表的增删查改

一、顺序表

(1)、什么是顺序表
在了解顺序表之前先,认识一下线性表。
线性表:是n个具有相同特性的数据元素的有限序列。线性表是在应用中被广泛使用的数据结构,常见的线性表:顺序表,链表,栈,队列,字符串等等。
线性表在逻辑上是连续的(想象中是连续的),在物理上不一定连续(内存中存储不一定连续,比如链表)。
顺序表:是线性表的一种,是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上进行增删查改。
(2)、如何使用?
顺序表分为:静态顺序表和动态顺序表。
静态顺序表:使用定长数组存储。
动态顺序表L:使用动态内存的数组存储。
顺序表的静态存储:

#define N 100//数组的大小
typedef int SLDateType;//想存储什么类型的数据,修改int 即可。
typedef struct SeqList
{
	SLDateType a[N];//定长数组
	size_t szie;//有效数据个数
	
}SeqList;

顺序表的静态存储:

typedef int SLDateType;
typedef struct Seqlist
{
	SLDateType* arr;//柔性数组,使用malloc开辟动态内存。
	SLDateType size;//已有数目
	SLDateType capacity;//容量
}Seqlist;

二、实现动态顺序表

还是使用多文件实现。
头文件:包含头文件和函数声明,定义的结构体和宏定义:

#pragma once//防止头文件被重复包含
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#pragma warning(disable:4996)
typedef int SLDateType;

typedef struct Seqlist
{
	SLDateType* arr;//柔性数组
	SLDateType size;//已有数目
	SLDateType capacity;//容量
}Seqlist;

//函数声明
//初始化ps函数
void SeqListInit(Seqlist *ps);

//尾插函数
void SeqListPushBack(Seqlist* ps,SLDateType x);

//尾删函数
void SeqListPopBack(Seqlist* ps);

//打印函数
void SeqListPrint(const Seqlist* ps);

//头插函数
void SeqListPushFront(Seqlist* ps, SLDateType x);

//头删函数
void SeqListPopFront(Seqlist* ps);

//顺序表寻找函数
int  SeqListFind(const Seqlist* ps, SLDateType x);

//顺序表销毁函数
void SeqListDestory(Seqlist* ps);

//顺序表中间插入函数
void SeqListInsert(Seqlist* ps, int pos, SLDateType x);

//顺序表中间删除函数
void SeqListErase(Seqlist* ps, int pos);

源文件 main.c 进行测试函数:

int main()
{
	Seqlist ps;
	//调用函数,调试
	return 0;
}

源文件SeqList.c实现函数功能:
我们定义了结构体变量,首先我们需要对ps进行初始化。
(1)、初始化函数SeqListInit函数:

void SeqListInit( Seqlist *ps)
{
	ps->arr = (SLDateType*)malloc(sizeof(SLDateType) * 4);
	//初始化,申请动态内存
	if (ps->arr == NULL)
	{
		printf("malloc failed");
		return;
	}
	ps->size = 0;
	ps->capacity = 4;//初始容量为4
}

(2)、尾插功能
在每次插入之前都要判断容量是否够用,用CheckSeqList(ps);
每添加一个size++;

void SeqListPushBack(Seqlist* ps, SLDateType x)
{
	assert(ps);
	CheckSeqList(ps);//判断是否需要扩容
	ps->arr[ps->size] = x;//将新值赋给下标为size的arr
	
	ps->size++;
}

(3)判断是否需要扩容函数CheckSeqList

void CheckSeqList(Seqlist* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		ps->capacity *= 2;//扩容成原来的两倍,最多浪费不到50%
		ps->arr=(SLDateType*)realloc(ps->arr, sizeof(SLDateType) * ps->capacity);
		if (ps->arr == NULL)
		{
			printf("realloc失败\n");
			return;
		}
	}
}

(4)尾删函数SeqListPopBack
只需要将最后一个数无效就好

void SeqListPopBack(Seqlist* ps)
{
	assert(ps);
	ps->size--;//减少数组中的有效数目,让最后一个数无效
}

(5)、头插函数
画个图理解一下:
将每一个只能向后移动,将arr下标size-1的值给szie ,size-2给size-1,依次空出arr[0],将x赋值给arr[0];
在这里插入图片描述

void SeqListPushFront(Seqlist* ps, SLDateType x)
{//将每一个只能向后移动,
	assert(ps);
	CheckSeqList(ps);
	int i = ps->size;//不能改变size的值
	while (i > 0)
	{
		ps->arr[i] = ps->arr[i - 1];
		i--;
	}
	ps->arr[0] = x;//把新值符给第一个
	ps->size++;
}

(6)、顺序表打印函数:

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

(7)头删函数:
1、可以用下标为size-1的值一个覆盖第一个,然后size–,但是会打乱原来的顺序,如图一样:在这里插入图片描述2、整体向左移动,覆盖第一个,size–,这样不会打乱顺序,如图:
在这里插入图片描述将每一个只能向左移动,将arr下标size-1的值给szie-2 ,size-2给size-3,最后覆盖arr[0];

代码实现如下:

void SeqListPopFront(Seqlist* ps)
{
	//可以用最后一个覆盖第一个,然后size--,但是会打乱原来的顺序
	/*ps->arr[0] = ps->arr[ps->size - 1];
	ps->size--;*/
	//也可以整体向<-移动,不会打乱顺序
	int i = 1;
	for (i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

(8)、中间插入函数:
给定一个位置在他的后边插入新值,只是将pos位置之后的向后移,也可以调用头插实现,
在这里插入图片描述d代码实现如下:

void SeqListInsert(Seqlist* ps, int pos, SLDateType x)
{//size是0  size是1  size是多个三种情况
	assert(ps);
	assert(pos < ps->size);//pos不能小于ps->size
	CheckSeqList(ps);
	int  end = ps->size;//pos位置到最后整体,向后移动一位,预留pos位置
	for (end; end > pos; end--)
	{
		ps->arr[end] = ps->arr[end - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

(9)中间删除函数:
和头删一样,用pos(要删掉的位置)后边的值向后移动覆盖pos位置的值。
在这里插入图片描述代码实现如下:

void SeqListErase(Seqlist* ps, int pos)//pos是位置
{
	
	assert(ps);
	assert(pos < ps->size);
	
	int start = pos;
	for (start; start < ps->size; start++)
	{
		ps->arr[start] = ps->arr[start + 1];
	}
	ps->size--;
}

(10)顺序表查找函数:
判断x与arr里边的值是否相等,相等返回下标,
没有相等的,就是找不到。

int  SeqListFind(const Seqlist* ps, SLDateType x)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			printf("找到了,下标是%d\n", i);
			return i;
		}
		
	}
	printf("找不到\n");
	return -1;
}

(11)、销毁顺序表函数
我们使用了malloc申请了动态内存,如果不释放,会发生内存泄漏。所以使用完顺序表,要销毁。

void SeqListDestory(Seqlist* ps)
//我们使用了malloc申请了动态内存,如果不释放,会发生内存泄漏
{
	free(ps->arr);
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

三、整体调试

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值