C语言动态顺序表的初步实现

阅读本文需掌握的知识:

  1. 多个文件协同操作
  2. typedef、realloc函数、指针、结构体
  3. 数组空间存储结构
  4. C语言基本语法

计算机世界中存在无穷无尽的数据,如果想要高效地利用这些数据,我们必须对数据作出一定管理规则,将相同特性的数据按照一定物理结构存储在一块方便取用,这就叫做数据结构
我们已经学习了最基本的数据结构:数组,有了数组的概念,我们今天来拓展一种新的数据结构——顺序表

顺序表的概念:

顺序表即具有相同特性的一类数据结构的统称,底层结构为数组,因此它的逻辑结构成线性,物理结构也呈线性,分为静态顺序表动态顺序表

//静态顺序表
struct SeqList
{
	int a[10];
	int size;
}

//动态顺序表
struct SeqList
{
	int* a;
	int size;
	int capacity;

静态顺序表代码简洁,无需考虑空间上的扩容与缩小,但是弊端也很明显,空间大了造成内存浪费,空间小了造成数据丢失(内存不够);动态顺序表空间大小灵活,可大可小视情况而定,但是代码书写较为繁琐。
本文下述代码段均以实现动态顺序表为例

顺序表的实现:

根据实际经验我们可以知道一个合格的顺序表所具备的操作应该有头插、尾插、头删、尾删、销毁、创建初始化一系列步骤

其中插入步骤最为复杂,我们率先讨论,插入数据之前应先考虑两种情况:空间足够or空间不足,倘若空间不足则需要扩容,空间足够则只需要在原有空间上进行数据移位即可
在这里插入图片描述

提示:所有函数操作需要传址调用(传值调用只是临时拷贝,不会对实参作出任何修改)
头文件的定义
SeqList.h

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

//定义顺序表
typedef int Date;//数据类型
typedef struct SeqList
{
	Date* a;//空间起始地址
	int size;//有效数据个数
	int capacity;//空间大小
}SL;

void init(SL*ps);//初始化
void destroy(SL*ps);//销魂
void head_insert(SL*ps,Date x);//增
void tail_insert(SL*ps,Date x);
void head_pop(SL*ps);//删
void tail_pop(SL*ps);
void print(SL*ps);//输出
bool isempty(SL*ps);//判断是否为空
void enlarge(SL*ps);//扩容

函数具体实现:
SeqList.c

#include "SeqList.h"
void init(SL* ps)
{
	ps->a=NULL;
	ps->size=ps->capacity=0;
}

void destroy(SL* ps)
{
	if(ps->a)
		free(ps);
	ps->a=NULL;
	ps->size=ps->capacity=0;
}

void enlarge(SL* ps)
{
	assert(ps);
	if(ps->size==ps->capacity)
		{
		int newcap=ps->capacity==0?4;capacity*2;
		//规定每一次扩容2倍
		Date* tmp=(Date*)realloc(ps->a,newcap*sizeof(Date));
		assert(tmp);
		ps->a=tmp;ps->capacity=newcap;
		}
}

void tail_insert(SL*ps,Date x)
{
	assert(ps);
	enlarge();
	ps->a[size]=x;
	ps->size++;
}

void head_insert(SL* ps,Date x)
{
	assert(ps);
	enlarge();
	for(size_t i=size;i>0;i--)
	{
		ps->a[i]=ps->a[i-1];
	}
	ps->a[0]=x;
	ps->size++;
}

void tail_pop(SL* ps)
{
	assert(ps);
	assert(!isempty(ps));
	ps->size--;
}

void head_pop(SL* ps)
{
	assert(ps);
	assert(!isempty(ps));
	for(size_t i=0;i<=size-2;i++)
	{
		ps->a[i]=ps->a[i+1];
	}
	ps->size--;
}

bool isempty(SL* ps)
{
	assert(ps);
	return ps->size==0;
}
void print(SL*)
{
	for(size_t i=0;i<size;i++)
		printf("%d ",ps->a[i]);
	printf("\n");
}

测试函数实现:
test.c

include "SeqList.h"
void test()
{
	SL s1;//先声明结构体变量!
	init(&s1);
	tail_insert(&s1, 1);
	tail_insert(&s1, 2);
	tail_insert(&s1, 3);
	tail_insert(&s1, 4);
	print(&s1);

	head_insert(&s1, 5);
	head_insert(&s1, 6);
	head_insert(&s1, 7);
	head_insert(&s1, 8);
	print(&s1);

	tail_pop(&s1);
	print(&s1);
	head_pop(&s1);
	print(&s1);

	destroy(&s1);
}
int main()
{
	test();

	return 0;
}

效果如图请添加图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shall#

你的鼓励将是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值