【数据结构】C--顺序表1.0版本(本文非常适合小白观看,已尽力详解,以及图解也是尽量列举)(上)

简介: 【数据结构】C--顺序表1.0版本(本文非常适合小白观看,已尽力详解,以及图解也是尽量列举)(上)

0.前言


   本篇文章包含了不少的代码测试情况,以及经过调试之后如何找出bug的情况,也悉数列举。本篇文章虽然没有菜单,是1.0版本,日后本菜鸟的代码能力提高之后会逐步完善。但是此文章经过了本人的详细思考,以及理解情况,也可以给大佬们和朋友们列举一些反例,也希望大家可以从中吸取经验,最后希望大佬们如果乐意的话可以考虑给我留下个免费的赞,您的支持是我创作的最大动力,感谢!


在讲解这一章开始时,我先说明一下什么是数据结构。


什么是数据结构?


数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系

数据元素的集合。

数据结构是由三部分进行组成,分别是:逻辑结构、存储结构和数据的运算


1.逻辑结构:

76cfaf4744fa4503b765f0ce9f59f04c.png

这里的一般线性表就是顺序表的意思。


1.1线性结构:

9fd6e2b63d8e43f0bbef4400188dd6b1.png

1.2非线性结构:

(1)集合

集合中的数据元素除了同属一个集合外,其它是没有关系的。

d8421e3566bf4a1cbb2a59a2a7360c06.png

(2)树形结构

794915416e094cf3b612f1f4dac80808.png

(3)图形结构或者网状结构

050eac7a741845b193127fd42099e7c6.png


2.存储结构

fedc3835b2e9445aaa8ce16d718b065b.png


一.线性表


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

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

4ce3e72ef5784c3e8d0951c5ea413502.png

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,

线性表在物理上存储时,通常以数组和链式结构的形式存储

97ce2982b70a4fabb5937eb09ea339aa.png


二.顺序表


概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存

储。在数组上完成数据的增删查改。


顺序表与数组的关系:(非常容易混淆)


这块我简单提一下顺序表和数组的关系:

对于数组而言:

数组的元素是可以随机存放的,因为:数组通过下标访问是可以任意存储的

49385f7099e54b70ba6c5dd181bed801.png

59b23cd571254d4a9e056ade16b8d9fc.png

e7757b9ed1674f7a81efffdf444f826b.png

可以看到值已经放进去了


对于顺序表而言:

顺序表是要连续存放的是,这个连续存放,不是指的是值连续,而是空间连续(意思是你存放的时候,不能跳着存,必须从0下标开始,依次向后存放)

8533a6fc844d4700893b696aeb04be7f.png

简单地讲:

顺序表不能随意存储,顺序表必须从0下标开始,依次向后存放,意思就是他是顺序存储的,不会出现空一个位置的情况。

顺序表一般可以分为:动态和静态顺序表,

动态顺序表:也是基于数组实现的,只不过它可以实现扩容,而数组是固定长度大小的


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

图解:

80f05751326a476e84f0266a17397c3f.png

定义静态顺序表:

#define N 10
typedef int SLDatatype;//这个地方可以避免写死类型是int,以后想换就换
struct SeqList
{
  SLDatatype a[N];//为了避免写死数组大小,需要改的时候到处改,那就使用宏定义
  int size;
};


静态顺序表的缺点:

如果存满了还想存入数据,那就不能继续存储了,因为空间是固定

#define N 10

N-->改成10000,如果这个地方要存储10001,那还是不够存储,如果存不满10000个空间,那会浪费空间

总体来说:给小了不够用,给多了浪费


因此:

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

大小,所以下面我们实现动态顺序表。


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

图解:

caaccc1204a743d5b82bf2612d96d971.png

定义动态顺序表

//动态顺序表
typedef int SLDatatype;//这个位置换成double会导致问题,可能会导致全元素都是0
typedef struct SeqList
{
  SLDatatype* a;//指向动态开辟的数组
  int size;  //存储的有效数据的个数
  int capacity;//容量空间的大小
}SL;//类型名重定义


接口实现

1️⃣ 初始化:SLInit

void SLInit(SL* psl);//动态顺序表初始化

错误的初始化:

3d94796447eb4bda955ce3d1739d1916.png

正确的初始化:

void SLInit(SL* psl)
{  
    //malloc扩容因为malloc类型是->void* malloc (size_t size);所以需要强制转换
  psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开4个比较合适
  //开辟失败会返回NULL,并打印错误信息
  if (psl->a == NULL)
  {
    perror("malloc fail");
    return;
  }
  psl->capacity = 4;//使用结构体指针指向访问对象的成员,当前容量
  psl->size = 0;//当前有效信息个数
}

图解:

3514bc32a9e24ef9b6bb0ff586cc03ae.png

2️⃣销毁:SLDestroy

SLDestroy(SL* psl);//顺序表销毁


void SLDestroy(SL* psl)//销毁不是整没了,而是还给操作系统了
{
  free(psl->a);//这里不free的话会产生野指针
  psl->a = NULL;
  psl->size = 0;
  psl->capacity = 0;
}

c05b3b41da514124b2bb6a43d91f26d4.png

3️⃣检查容量:SLCheckCapacity

说明一下:

realloc是新增到多少空间,比如说我本来是20个int的空间,(int*)realloc(arr,40),这是把空间整体扩到40个int,不是说增了多少,后面这个40的位置是整体的大小,而不是20+40=60。

这个realloc的知识点可以看这篇文章,比较详细地展开说明:http://t.csdn.cn/H3I26

void SLCheckCapacity(SL* psl)
{
  if (psl->size == psl->capacity)//有效信息的个数等于当前容量
  {
    SLDatatype* tmp =(SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * psl->capacity * 2);
    if (tmp == NULL)//申请空间过大可能会申请失败
    {
      perror("realloc fail");
      return;
    }
    psl->a = tmp;//原地扩容用的是原来的地址,异地扩容用的是新的
    psl->capacity *= 2;//当前容量*2
  }
}

图解:

19a113c60839480d9d61b4e956b5c7c4.png

(SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * psl->capacity * 2);

这个地方扩2倍是比较合适的。

4️⃣顺序表打印:SLPrint

void SLPrint(SL*psl);//顺序表打印

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

打印顺序表的每个元素

5️⃣尾部插入:SLPushBack

void SLPushBack(SL* psl, SLDatatype x); //顺序表尾插

void SLPushBack(SL* psl, SLDatatype x)
{
  assert(psl);  
  SLCheckCapacity(psl);//容量初始值为4,检查当前容量,不够则扩容
  psl->a[psl->size++] = x;
}

5fa8c31b6eb0444e96d2a023184444ad.png

调用测试尾部插入的代码:

void TestSeqList1()
{
  SL s;
  SLInit(&s);
  SLPushBack(&s, 1);
  SLPushBack(&s, 1);
  SLPushBack(&s, 2);
  SLPushBack(&s, 3);
  SLPushFront(&s,5);
  SLPrint(&s);
  SLDestroy(&s);
}


执行:

e7a17a8a79fc46a58af4b03adf3592dc.png

相关文章
|
1月前
|
存储 编译器 C语言
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
49 2
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
18天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
49 3
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
1月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
30 6
|
1月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
23 3
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
19 2
|
1月前
|
存储 算法 索引
【数据结构】——顺序表
【数据结构】——顺序表
|
1月前
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
22 1
|
1月前
|
存储
数据结构1——顺序表
数据结构1——顺序表
17 1

热门文章

最新文章