探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口)

这篇具有很好参考价值的文章主要介绍了探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在我们的数据结构探索中,我们已经探讨时间复杂度、空间复杂度。大家可以移步到我的上篇文章:

打开数据结构大门:深入理解时间与空间复杂度

今天,我们将深入研究另一个重要的主题——顺序表

全部的源代码大家可以去我github主页进行浏览:Nerosts/just-a-try: 学习c语言的过程、真 (github.com)


在介绍顺序表前,先来了解一下线性表的概念,后面一段时间讲到的数据结构也都属于线性表。

一.线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使

用的数据结构,常见的线性表:顺序表、链表、栈、字符串…

  • 线性表在==逻辑上(我们想象它是)==是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储

探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口),数据结构,数据结构,c语言,开发语言,学习,算法
探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口),数据结构,数据结构,c语言,开发语言,学习,算法


二.顺序表

2.1概念和结构

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

  1. 静态顺序表:使用定长数组存储元素
#define N 7
typedef int SLDataTypt;
struct SeqList
{
	int a[N];//数组长度固定
	int size;//有效数据的个数
			//因为数组长度固定,也不需要capacity来表示容积
};
  1. 动态顺序表:使用动态开辟的数组存储
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* a;
	int size;//the number of valid data
	int capacity;//the size of volumetric space
}SL;

2.2项目文件方面规划

探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口),数据结构,数据结构,c语言,开发语言,学习,算法

  • 头文件SquList.h:用来基础准备,顺序表的基本框架,函数的声明
  • 源文件SeqList.h:用来各种接口函数的具体实现
  • 源文件test.h:用来测试功能是否有问题

2.3基本功能实现

各接口总体一览

void SLInit(SL* ps); //初始化
void SLDestroy(SL* ps);//销毁
void SLPrint(SL* ps);//打印

void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopFront(SL* ps);//头删
void SLPopBack(SL* ps);//尾删

// 顺序表查找
int SLFind(SL* ps, SLDataType x);//返回下标索引
// 顺序表在pos位置插入x
void SeqListInsert(SL* ps, int pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SL* ps, int pos);

初始化、销毁、打印

void SLInit(SL* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);
	free(ps->a);//pa->a 是realloc动态开辟的
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

void SLPrint(SL* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)//size means the number of valid data
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

尾插

void CheckCapacity(SL* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* new = realloc(ps->a,sizeof(SLDataType) * newcapacity);
		if (new == NULL)
		{
			perror("realloc");
			return -1;
		}
		ps->a = new;
		ps->capacity = newcapacity;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	CheckCapacity(ps);//检查此时容积是否存满
	ps->a[ps->size] = x;
	ps->size++;
}

SLPushBack函数用于向单链表尾部添加元素

  • 首先使用assert宏判断ps是否为空指针
  • 然后调用CheckCapacity函数检查容量是否已满,若已满则进行扩容操作
  • 接着将元素x添加到单链表数组的末尾,然后更新单链表的大小

CheckCapacity函数用于检查单链表的容量是否已满,如果已满则进行扩容操作

  • 首先使用assert宏判断ps是否为空指针
  • 然后判断如果单链表的大小等于容量,说明已满,需要进行扩容操作。新的容量设置为原容量的两倍,如果原容量为0,则新容量设置为4
  • 然后使用realloc函数重新分配内存,将原数组指针ps->a指向的内存空间扩展到新的容量大小,如果内存分配失败则输出错误信息并返回-1
  • 最后更新ps->a指向新的内存空间,同时更新容量为新的容量值

这两个函数结合起来可以实现向单链表尾部添加元素并在需要时自动扩容的功能

头插

void SLPushFront(SL* ps, SLDataType x) //将所有元素向后迁移一个,把第一个位置空出来
{
	assert(ps);
	CheckCapacity(ps);
	memmove(ps->a + 1, ps->a, sizeof(SLDataType) * ps->size);
	ps->a[0] = x;
	ps->size++;
}

函数的作用是将所有元素向后移动一个位置,从而空出第一个位置,然后在第一个位置插入新的元素x

  • 首先使用assert宏判断ps是否为空指针,然后调用CheckCapacity函数检查容量是否已满,若已满则进行扩容操作
  • 接着使用memmove函数将数组中的元素整体向后移动一个位置,从ps->a的位置开始,移动sizeof(SLDataType) * ps->size个字节的数据,移动到ps->a + 1的位置,即每个元素向后移动一个位置。
  • 然后将新元素x插入到第一个位置ps->a[0],并更新单链表的大小

头删

void SLPopFront(SL* ps)//整体向前偏移
{
	assert(ps);
    assert(ps->size > 0);//保证有元素来删
	memmove(ps->a, ps->a+1, sizeof(SLDataType) * ps->size);
	ps->size--;
}

尾删

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	ps->size--;
}

查找

int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->a[i])
		{
			return i;
		}
	}
	return -1;
}

插入

void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	CheckCapacity(ps);
	memmove(ps->a + pos + 1, ps->a + pos, sizeof(SLDataType) * (ps->size - pos));
	ps->a[pos] = x;
	ps->size++;
}

删除

void SeqListErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	int start = pos;
	while (start < ps->size)
	{
		ps->a[start] = ps->a[start + 1];
		start++;
	}
	ps->size--;
}

2.4测试

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void test1()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	printf("尾插三个:");
	SLPrint(&s);

	SLPushFront(&s, 0);
	SLPushFront(&s, 0);
	printf("头插2个:");
	SLPrint(&s);

	SLPopFront(&s);
	SLPopFront(&s);
	printf("头删2个:");
	SLPrint(&s);

	SLPopBack(&s);
	SLPopBack(&s);
	printf("尾删2个:");
	SLPrint(&s);

	SLDestroy(&s);
}

int main()
{
	test1();
	return 0;
}

结果如下:

探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口),数据结构,数据结构,c语言,开发语言,学习,算法

可见功能都正常运行


这次顺序表的内容就先到这里啦!感谢大家支持文章来源地址https://www.toymoban.com/news/detail-771131.html

到了这里,关于探索顺序表:数据结构中的秩序之美(c语言实现常见功能接口)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 堆积如山:探索数据结构中的堆

    前言 欢迎来到小K的数据结构专栏的第十一小节,本节将为大家带来堆的详解并带来堆题目的讲解(✨当然也为大家准备了完整的源码 )~希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾 ✨ 在讲堆之前我们先看看满二叉树和完全二叉树~ 一、满二叉树 我们

    2024年02月08日
    浏览(37)
  • 探索树形数据结构,通识树、森林与二叉树的基础知识(专有名词),进一步利用顺序表和链表表示、遍历和线索树形结构

      结点之间有分支,具有层次关系 树的定义 : 树 (tree)是n(n≥0)个有限集。 若n = 0,则称为空树; 若n 0,则它满足如下两个条件: 有且仅有一个特定的称为根(Root)的结点; 其余结点可分为m(m≥0)个互不相交的有限集T1,T2,T3,.....,Tm,其中每一个集合本身又是一棵树,并称为根的

    2024年02月01日
    浏览(33)
  • 原神世界中的顺序表:派蒙的趣味数据结构讲解

    派蒙,那个总是带着疑问眼神的小家伙,是原神世界中的小精灵。他总是充满好奇心,无论是对新的冒险者,还是对各种奇妙的现象。而他的另一个身份,则是原神世界中的数据结构大师。 一天,派蒙遇到了旅行者小森,他带着一肚子的疑问和困惑。 小森:“派蒙,我一直

    2024年02月11日
    浏览(46)
  • 数据结构与算法之美 | 栈

    栈结构:后进者先出,先进者后出 栈是一种“操作受限”的线性表 当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,这时我们就应该首选“栈”这种数据结构 使用数组实现:顺序栈 使用链表实现:链式栈 函数调用栈 操作系统给每个线程

    2024年02月08日
    浏览(42)
  • 【数据结构初阶】五、线性表中的栈(C语言 -- 顺序表实现栈)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】四、线性表里的链表(带头+双向+循环 链表 -- C语言实现)_高高的胖子的博客

    2024年02月08日
    浏览(35)
  • 数据结构与算法之美 | 排序(3)

    桶排序(Bucket sort) 基本思想 : 将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。 桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。 桶排序常常用在外部排序[^1]中。 我们有 10 GB 的订单数据,我们希望按订单金额(

    2024年02月08日
    浏览(31)
  • 数据结构之美:如何优化搜索和排序算法

    🎉欢迎来到数据结构学习专栏~数据结构之美:如何优化搜索和排序算法 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:数据结构学习 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水

    2024年02月08日
    浏览(39)
  • 探索Redis特殊数据结构:Bitmaps(位图)在实际中的应用

    Redis官方提供了多种数据类型,除了常见的String、Hash、List、Set、zSet之外,还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic(HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Configuration)和Time series。这些数据类型在Redis的数据结构中发挥着各自独特的作用。

    2024年01月19日
    浏览(32)
  • 探索Redis特殊数据结构:Geospatial(地理位置)在实际中的应用

    Redis官方提供了多种数据类型,除了常见的String、Hash、List、Set、zSet之外,还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic(HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Configuration)和Time series。这些数据类型在Redis的数据结构中发挥着各自独特的作用。

    2024年02月20日
    浏览(33)
  • 数据结构与算法之美学习笔记:48 | B+树:MySQL数据库索引是如何实现的?

    本节课程思维导图: 作为一个软件开发工程师,你对数据库肯定再熟悉不过了。作为主流的数据存储系统,它在我们的业务开发中,有着举足轻重的地位。在工作中,为了加速数据库中数据的查找速度,我们常用的处理思路是,对表中数据创建索引。那你是否思考过,数据库

    2024年01月16日
    浏览(59)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包