【数据结构】线性表之顺序表

这篇具有很好参考价值的文章主要介绍了【数据结构】线性表之顺序表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、线性表的定义

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

数组形式

【数据结构】线性表之顺序表

链表形式

【数据结构】线性表之顺序表

二、顺序表

1. 顺序表的定义

顺序表是一种线性数据结构,通过连续的内存空间存储元素,可以随机访问任何位置的元素。它支持在常量时间内进行插入、删除和访问操作,但在插入或删除元素时可能需要移动后续元素,导致时间复杂度为O(n)

2. 顺序表的结构

2.1 静态顺序表

静态顺序表使用定长数组,当数组存储满后则不能再进行存储。
【数据结构】线性表之顺序表

2.2 动态顺序表

动态顺序表使用动态申请的数组进行存储,当顺序表被存满后,会自动扩大容量。

【数据结构】线性表之顺序表

【数据结构】线性表之顺序表

3. 动态顺序表的接口实现

3.1 顺序表的接口

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);

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);

3.2 接口的实现

void SeqListInit(SeqList* ps)
{
	//动态申请十个 SLDateType 类型大小的空间
	ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 10);
	//判断是否开辟成功
	if (ps->a == NULL)
	{
		perror("malloc");
		return;
	}  
	ps->size = 0;        //顺序表初始化,顺序表内无数据,则赋值为 0
	ps->capacity = 10;   //容量为动态申请的元素个数
}


void SeqListDestroy(SeqList* ps)
{
	//将动态申请的空间释放
	free(ps->a);
	ps->a = NULL;
}

int CheckSeqList(SeqList* ps)
{
	//检查顺序表是否被填满
	if (ps->capacity == ps->size)
	{
		//若填满则将动态申请的内存扩大为原来的两倍
		SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * (ps->capacity * 2));
		//定义一个变量接收扩大后返回空间的首地址
		//目的:若开辟失败也不会改变原来的内存
		if (tmp == NULL)
		{
			perror("realloc");
			return 0;
		}
		ps->a = tmp;
		//将容量变成原来的两倍
		ps->capacity *= 2;
	}
	return 1;
}


void SeqListPushBack(SeqList* ps, SLDateType x)
{
	//判断顺序表是否为满,未满则进行下面的步骤
	//若满了,则先扩容,再进行下面的步骤
	if (CheckSeqList(ps) == 0)
	{
		return;
	}
	
	//将需要尾插的数据放在下标为size的数组中
	ps->a[ps->size] = x;
	//存储的元素加一
	ps->size++;
}

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

void SeqListPushFront(SeqList* ps, SLDateType x)
{
	//判断顺序表是否为满,未满则进行下面的步骤
	//若满了,则先扩容,再进行下面的步骤
	if (CheckSeqList(ps) == 0)
	{
		return;
	}

	//下面省略的代码是没有用随机插入函数实现的
	/*int i = 0;
	for (i = ps->size - 1; i >= 0; i--)
	{
		//将所有的元素向后移动一位
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;   //将需要插入的元素放在首元素的位置
	ps->size++;*/	//存储元素个数加一
	
	//下面省略的代码是没有用随机插入函数实现的,并使用memmove函数移动数组
	
	/*memmove(ps->a + 1, ps->a, sizeof(SLDateType) * ps->size);
	ps->a[0] = x;
	ps->size++;*/
	
	//该代码是使用随机插入函数实现的
	SeqListInsert(ps, 0, x);
	
}


void SeqListPopFront(SeqList* ps)
{
	//下面省略的代码是没有用随机删除函数实现的
	//断言:顺序表为空不能删除
	//assert(ps->size != 0);
	/*int i = 0;
	//将首元素后面的元素全部向前移动一位
	for (i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;*/  //存储元素个数减一

	//下面省略的代码是没有用随机删除函数实现的,并使用memmove函数移动数组
	/*memmove(ps->a, ps->a + 1, sizeof(SLDateType) * (ps->size - 1));
	ps->size--;*/ 
	
	//该代码是使用随机删除函数实现的
	SeqListErase(ps, 0);
}

void SeqListPopBack(SeqList* ps)
{
	//下面省略的代码是没有用随机删除函数实现的
	
	//断言:顺序表为空不能删除
	/*assert(ps->size != 0);
	ps->size--;*/ //存储元素个数减一
	
	//该代码是使用随机删除函数实现的
	SeqListErase(ps , ps ->size - 1);
}


int SeqListFind(SeqList* ps, SLDateType x)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}


void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	int i = 0;
	//需要插入的位置不能在size下标元素的后面
	//原因是size - 1 下标中的元素是最后一个元素
	assert(ps->size >= pos);
	/*for (i = ps->size - 1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;*/

	memmove(ps->a + pos + 1, ps->a + pos, sizeof(SLDateType)*(ps->size - pos));
	ps->a[pos] = x;
	ps->size++;
}

void SeqListErase(SeqList* ps, int pos)
{
	//顺序表不能为空
	assert(ps->size != 0);
	int i = 0;
	//将需要删除元素的后面的元素全部向前移动一位
	for (i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

三、顺序表总结

1. 动态顺序表的优点

(1)可以根据需要动态地分配内存,灵活性更高。
(2)可以避免静态数组可能出现的内存浪费问题。
(3)由于内存空间是动态分配的,因此可以处理数据量不确定或者变化的情况。

2. 动态顺序表的缺点

(1)动态内存分配比静态内存分配要慢一些,会增加程序的运行时间。
(2)需要手动管理内存,包括申请和释放,容易出现内存泄漏和内存碎片等问题。
(3)难以预测、控制内存的使用情况,容易出现因为内存不足而导致程序崩溃的情况

结尾

如果有什么建议和疑问,或是有什么错误,希望大家能够提一下。
希望大家以后也能和我一起进步!!
如果这篇文章对你有用的话,希望能给我一个小小的赞!文章来源地址https://www.toymoban.com/news/detail-439921.html

到了这里,关于【数据结构】线性表之顺序表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【数据结构】线性表之栈、队列

    【数据结构】线性表之栈、队列

    前面两篇文章讲述了关于线性表中的顺序表与链表,这篇文章继续讲述线性表中的 栈和队列。 这里讲述的两种线性表与前面的线性表不同,只允许在一端入数据,一段出数据,详细内容请看下面的文章。 顺序表与链表两篇文章的链接: 线性表之顺序表 线性表之链表 注意:

    2024年02月06日
    浏览(43)
  • 【数据结构】线性表之链表

    【数据结构】线性表之链表

    上一篇文章讲述了线性表中的顺序表,这篇文章讲述关于链表的定义、类别、实现、多种不同链表的优缺点和链表与顺序表的优缺点。 关于上一篇文章的链接:线性表之顺序表 链表是一种物理存储结构上 非连续、非顺序 的存储结构,数据元素的逻辑顺序是通过链表中的指针

    2024年02月05日
    浏览(50)
  • 【数据结构】线性表(一)线性表的定义及其基本操作(顺序表插入、删除、查找、修改)

    【数据结构】线性表(一)线性表的定义及其基本操作(顺序表插入、删除、查找、修改)

    目录 一、线性表 1. 线性表的定义 2. 线性表的要素 二、线性表的基本操作 三、线性表的顺序存储结构 1. 定义 2. 顺序表的操作       a. 插入操作 b. 删除操作 c. 查找操作 d. 修改操作 e. 代码实例          一个线性表是由零个或多个 具有相同类型的结点 组成的有序集合。

    2024年02月03日
    浏览(49)
  • 数据结构 线性表的定义和基本操作(以顺序表为例)

    数据结构 线性表的定义和基本操作(以顺序表为例)

    名人说:一花独放不是春,百花齐放花满园。——《增广贤文》 作者:Code_流苏(CSDN) (一个喜欢古诗词和编程的Coder😊) 以下代码个人分享出来,仅供学习交流,且仅在CSDN平台发布,未经授权禁止二次转发。 〇、线性表是什么? 1、定义 线性表 是具有 相同数据类型 的 n(

    2024年02月12日
    浏览(49)
  • 数据结构:线性表之-单向链表(无头)

    数据结构:线性表之-单向链表(无头)

    目录 什么是单向链表 顺序表和链表的区别和联系 顺序表: 链表: 链表表示(单项)和实现 1.1 链表的概念及结构 1.2单链表(无头)的实现 所用文件 将有以下功能: 链表定义 创建新链表元素 尾插 头插 尾删 头删 查找-给一个节点的指针 改 pos位置之前插入 删除pos位置的值 成品

    2024年02月09日
    浏览(51)
  • C语言数据结构——线性表之栈和队列

    C语言数据结构——线性表之栈和队列

    为什么会定义栈和队列这两种数据结构呢? 原因在于: 之所以会定义栈和队列这样的数据结构 是因为他们有两大特性 : 第一: 他们可以保存程序运行路径中各个点的信息,以便用于回溯操作或其他需要访问已经访问过的节点信息的操作。 比如: 栈用于解决迷宫问题,就

    2023年04月11日
    浏览(46)
  • 数据结构:线性表之-循环双向链表(万字详解)

    数据结构:线性表之-循环双向链表(万字详解)

    目录 基本概念 1,什么是双向链表 2,与单向链表的区别 双向链表详解 功能展示: 1. 定义链表 2,创建双向链表 3,初始化链表 4,尾插 5,头插 6,尾删 判断链表是否被删空 尾删代码 7,头删 8,pos位置之前插入 优化后的头插 优化后的尾插 9,删除pos位置的节点 优化后的尾删 优

    2024年02月09日
    浏览(13)
  • 数据结构第三课 -----线性表之双向链表

    数据结构第三课 -----线性表之双向链表

    🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 ​🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉🎉🎉🎉🎉 🎂 🎂作者id:老秦包你会, 🎂 简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂 喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂

    2024年02月05日
    浏览(48)
  • 【数据结构】线性表之单链表(讲解实现——带动图理解)

    【数据结构】线性表之单链表(讲解实现——带动图理解)

    单链表的优点 1.头部和中间插入或删除数据效率高,无需挪动。 2.按照需求申请释放空间,无需担心空间不够用。 单链表的缺点 1.不可以进行下标随机访问。 2.复杂度是O(n) 3.反向遍历困难 单链表是线性表的一种,单链表是链式存储的线性表,不同于单链表, 链表在内存空间

    2024年02月06日
    浏览(53)
  • 数据结构三:线性表之单链表(带头结点单向)的设计与实现

    数据结构三:线性表之单链表(带头结点单向)的设计与实现

            线性表的链式存储结构正是所谓的单链表,何谓单链表?通过地址将每一个数据元素串起来,进行使用,这可以弥补顺序表在进行任意位置的插入和删除需要进行大量的数据元素移动的缺点,只需要修改指针的指向即可;单链表的种类又可划分为很多种,本篇博客详

    2024年02月19日
    浏览(54)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包