详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改

这篇具有很好参考价值的文章主要介绍了详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、线性表

二、顺序表

2.1概念及结构

2.2接口实现

2.3动态顺序表的创建

2.3动态顺序表的初始化

2.3.1传值初始化

2.3.2传址初始化

2.4动态顺序表的清空

2.5动态顺序表的扩容

2.6动态顺序表内容的打印

三、动态顺序表的使用

3.1尾插尾删

3.1.1尾插

3.1.2尾删

3.2头插头删

3.2.1头插

3.2.2头删

3.3在pos位置插入x

3.4删除pos位置的值

3.5修改某个位置的值

四、完整代码


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改,数据结构初阶(C语言),数据结构

二、顺序表

2.1概念及结构

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

顺序表一般分为:

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

//静态顺序表
#define N 100
struct SeqList
{
	int a[N];//定长数组
	int size;//有效数据的个数
};

 详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改,数据结构初阶(C语言),数据结构

缺点:不是很灵活

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

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改,数据结构初阶(C语言),数据结构

2.2接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以下面我们实现动态顺序表。

所谓动态其实指的这个结构体里的指针是动态内存开辟来的,是可变的,用的时候动态开辟,不够的话继续开辟,程序结束的时候释放。

2.3动态顺序表的创建

typedef int SLDatatype;//将int重命名为SLDatatype
typedef struct SeqList
{
	SLDatatype* a;//指向动态开辟的数组

	SLDatatype capacity;//容量
	SLDatatype size;//有效数据的个数

}SL;//将结构体SeqList重命名为SL

2.3动态顺序表的初始化

2.3.1传值初始化

//传值初始化
void SLInit(SL s)
{
	s.a = NULL;
	s.size = 0;
	s.capacity = 0;
}

 函数那个章节我们学过形参只是实参的临时拷贝,并没有实际作用,生命周期短,出了函数的作用域就会销毁,我们不考虑这种初始化方式。

2.3.2传址初始化

//传址初始化
void SLInit(SL* ps)
{
	ps->a = 0;
	ps->capacity = 0;
	ps->size = 0;
}
void SLInit(SL* ps)
{
	ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间
	if (ps->a == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}
	ps->capacity = 4;//开辟了空间就要给容量赋值
	ps->size = 0;
}

上面两种初始化方式都可以给予结构体成员变量赋值,但是我们使用第二种,因为第二种为我们开辟了空间。

2.4动态顺序表的清空

void SLDestr(SL* ps)
{
	free(ps->a);
	ps->a = NULL;

	ps->capacity = 0;//内存释放,容量清零
	ps->size = 0;//内存释放,有效数据清零
}

2.5动态顺序表的扩容

void SLCheckcapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数

		if (tmp == NULL)
        //判断是否扩容失败
		{
			perror("realloc failed");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;//扩容后修改原来的容量
	}
}

这就是所谓的动态,当我们空间不够时,就需要开辟新的空间,使用realloc函数要注意是否开辟成功,定义一个中间指针,当开辟成功时将这个指针赋值给动态数组中的指针。 

2.6动态顺序表内容的打印

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

size为有效数据个数,使用循环打印其中的有效数据。 

三、动态顺序表的使用

3.1尾插尾删

3.1.1尾插

void SLPushBack(SL* ps, SLDatatype x)
{
	SLCheckcapacity(ps);//检查空间是否足够插入
	ps->a[ps->size] = x;//赋值
	ps->size++;//插入一个有效数据,有效数据个数加一
}

 首先一定要检查规矩是否足够,根据上面开辟的空间,容量为4,有效数据为size为0,所以从第一个空间开始插入数据。

3.1.2尾删

//尾删
void SLPopBack(SL* ps)
{
	assert(ps->size > 0);//判断是否会造成越界
	if (ps->size == 0)
	{
		return;
	}
	ps->size--;//删除一个数据,有效数据个数减一
}

插入数据后size的大小也会变化,数组中最后一个数字的下标刚好和size的大小一样我们只需要将size减1就行。 

3.2头插头删

3.2.1头插

void SLPushFront(SL* ps, SLDatatype x)
{
	SLCheckcapacity(ps);//检查空间是否足够
	int end = ps->size;
	while (end > 0)
	{
		ps->a[end] = ps->a[end - 1];//将前一个数据后移动
		end--;
	}
	ps->a[0] = x;//将x赋给初始位置
	ps->size++;//加入一个数字,有效数据个数加1
}

 老规矩一定要检查空间是否足够,头部插入数据我们只需要将原来的数据往后移动一格就将第一格的位置空出来,再将数值插入就行,插入一个数据,有效数据加1即可。

3.2.2头删

void SLPopFront(SL* ps)
{
	assert(ps->size > 0);//防止越界访问
	if (ps->size==0)
	{
		return;
	}
	int begin = 0;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin+1];//将后一个数据往前移动
		begin++;
	}
	ps->size--;//减少一个数字,有效数据减1
}

这里的删除并不是真正意义上的删除,我们只需要将原来的数据往前移动一位使后一位的数据覆盖在前一位,这就做到了删除,顺便再将有效数据减1就行。 

3.3在pos位置插入x

void SLInsert(SL* ps, int pos, int x)
{
	assert(pos >= 0 && pos <= ps->size);//防止越界访问
	SLCheckcapacity(ps);
	int end = ps->size;
	while (end >=pos)
	{
		ps->a[end] = ps->a[end-1];//和头插的思想差不多,将数据后移
		end--;
	}
	ps->a[pos] = x;//将x赋值给pos位置
	ps->size++;//有效数据加1
}

我们可以这样理解:将pos看成初始位置,是不是就转化为头插了?按照头插的思想就可以完成在pos位置上插入x。 

3.4删除pos位置的值

void SLErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size);//防止越界访问
	SLCheckcapacity(ps);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin + 1];//和头删的思想差不多,将数据前移
		begin++;
	}
	ps->size--;//有效数据减1
}

我们会发现3.4和3.5不仅可以做到某个位置值的插入和删除,也可以做到尾插尾删和头插头删。 

3.5修改某个位置的值

void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{
	assert(pos >= 0 && pos < ps->size);//防止越界
	ps->a[pos] = x;
}

 这样修改某个位置的值看起来是挺麻烦,但是是为了安全考虑。

四、完整代码

#define _CRT_SECURE_NO_WARNINGS 67
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//静态顺序表
//#define N 100
//struct SeqList
//{
//	int a[N];//定长数组
//	int size;//有效数据的个数
//};


//动态顺序表

//创建
typedef int SLDatatype;
typedef struct SeqList
{
	SLDatatype* a;//指向动态开辟的数组

	SLDatatype capacity;//容量
	SLDatatype size;//有效数据的个数

}SL;
//传值初始化
//void SLInit(SL s)
//{
//	s.a = NULL;
//	s.size = 0;
//	s.capacity = 0;
//}
//传址初始化
//void SLInit(SL* ps)
//{
//	ps->a = 0;
//	ps->capacity = 0;
//	ps->size = 0;
//}
void SLInit(SL* ps)
{
	ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间
	if (ps->a == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}
	ps->capacity = 4;
	ps->size = 0;
}
//清空
void SLDestr(SL* ps)
{
	free(ps->a);
	ps->a = NULL;

	ps->capacity = 0;
	ps->size = 0;
}
//打印
void SLprint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
//检查容量
void SLCheckcapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数

		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
}
//尾插
void SLPushBack(SL* ps, SLDatatype x)
{
	SLCheckcapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{
	assert(ps->size > 0);
	if (ps->size == 0)
	{
		return;
	}
	ps->size--;
}
//头插
void SLPushFront(SL* ps, SLDatatype x)
{
	SLCheckcapacity(ps);
	int end = ps->size;
	while (end > 0)
	{
		ps->a[end] = ps->a[end - 1];
		end--;
	}
	ps->a[0] = x;
	ps->size++;
}
//头删
void SLPopFront(SL* ps)
{
	assert(ps->size > 0);
	if (ps->size==0)
	{
		return;
	}
	int begin = 0;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin+1];
		begin++;
	}
	ps->size--;
}
//在pos位置插入x
void SLInsert(SL* ps, int pos, int x)
{
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);
	int end = ps->size;
	while (end >=pos)
	{
		ps->a[end] = ps->a[end-1];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}
//删除pos位置的值
void SLErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}
int SLFind(SL* ps, int x)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
			return i;
	}
	return -1;
}

void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{
	assert(pos >= 0 && pos < ps->size);
	ps->a[pos] = x;
}
int main()
{
	SL s1;
	//传值初始化
	//SLInit(s1);
	//传址初始化
	SLInit(&s1);
	//尾插
	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	SLPushBack(&s1, 6);
	SLPushBack(&s1, 7);
	//尾插测试
	printf("尾插:\n");
	SLprint(&s1);
	//尾删
	SLPopBack(&s1);
	//尾删测试
	printf("尾删:\n");
	SLprint(&s1);
	//头插
	SLPushFront(&s1,10);
	//头插测试
	printf("头插:\n");
	SLprint(&s1);
	//头删 
	SLPopFront(&s1);
	//头删测试
	printf("头删:\n");
	SLprint(&s1);
	//在pos位置插入x
	SLInsert(&s1, 0, 100);
	//pos插入x测试
	printf("pos位置插入x\n");
	SLprint(&s1);
	//删除pos位置的值
	SLErase(&s1, 0);
	//测试
	printf("删除pos位置的值\n");
	SLprint(&s1);


	//改
	SLModify(&s1, 2, 1);
	printf("修改某个位置上的值:\n");
	//
	SLprint(&s1);
	//清空
	SLDestr(&s1);
	return 0;
}

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改,数据结构初阶(C语言),数据结构文章来源地址https://www.toymoban.com/news/detail-701531.html

到了这里,关于详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构初阶】顺序表

    线性表(linear list) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上

    2024年02月02日
    浏览(36)
  • 数据结构(初阶)第二节:顺序表

    数据结构(初阶)第一节:数据结构概论-CSDN博客 从本文正式进入对数据结构的讲解,开始前友友们要有C语言的基础,熟练掌握 动态内存管理 、 结构体 、 指针 等章节,方便后续的学习。 顺序表(Sequence List) 顺序表的分类 静态顺序表 动态顺序表 顺序表的功能 初始化 扩

    2024年04月12日
    浏览(26)
  • 数据结构初阶--二叉树的顺序结构之堆

    目录 一.堆的概念及结构 1.1.堆的概念 1.2.堆的存储结构 二.堆的功能实现 2.1.堆的定义 2.2.堆的初始化 2.3.堆的销毁 2.4.堆的打印 2.5.堆的插入 向上调整算法 堆的插入 2.6.堆的删除 向下调整算法 堆的删除 2.7.堆的取堆顶元素 2.8.堆的判空 2.9.堆的求堆的大小 三.堆的创建 3.1.向上调

    2024年02月14日
    浏览(33)
  • 初阶数据结构之---二叉树的顺序结构-堆

    今天要讲的堆,不是操作系统虚拟进程地址空间中(malloc,realloc等开空间的位置)的那个堆,而是数据结构中的堆,它们虽然名字相同,却是截然不同的两个概念。堆的底层其实是 完全二叉树 ,如果你问我,完全二叉树是什么。好吧,那我先从树开始讲起,开始我们今天的

    2024年03月14日
    浏览(47)
  • 数据结构(初阶):顺序表实战通讯录

    数据结构(初阶)第一节:数据结构概论-CSDN博客 数据结构(初阶)第二节:顺序表-CSDN博客         本文将以C语言和顺序表实现通讯录基础管理,实现功能包括增、删、改、查等,在实现相关功能时需要用到在第二节中顺序表的相关内容,需要友友们掌握顺序表的相关

    2024年04月16日
    浏览(27)
  • 初阶数据结构:顺序表相关题目练习

    在对顺序表这一数据结构进行了学习与自实现后,我明白了顺序表的是使用了 物理地址上连续的数组模型 实现的,而 插入删除 的操作都会涉及到其中 数据的挪动与边界问题 。接下来,就结合算法时空间复杂的要求来对这一相关问题通过几道题目进行巩固练习。 题目要求:

    2024年01月20日
    浏览(36)
  • 【数据结构初阶】顺序表和链表(1)

    线性表(linear list) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上

    2024年02月08日
    浏览(34)
  • 【数据结构初阶】二、 线性表里的顺序表

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】一. 复杂度讲解_高高的胖子的博客-CSDN博客  =======================================

    2024年02月09日
    浏览(32)
  • 【数据结构初阶】二、 线性表里的顺序表(C语言实现顺序表)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】一. 复杂度讲解_高高的胖子的博客-CSDN博客  =======================================

    2024年02月08日
    浏览(30)
  • 数据结构初阶之顺序表(C语言实现)

    顺序表是数据结构里面很基础的一类,它是线性表的一种,其它线性表还有链表、栈和队列等,今天来和博主一起学习关于顺序表的知识吧。 顺序表,它分为两类: 动态顺序表 和 静态顺序表 ,这两个表的区别就是 前者的空间不固定 ,是 支持扩容 的,后者的 空间是固定

    2024年02月03日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包