数据结构——顺序表

简介: 数据结构——顺序表

一、 数据结构相关概念

1.1  什么是数据结构

数据结构是由“数据”和“结构”两词组合⽽来。


数据:常⻅的数值1、2、3、4.....、教务系统⾥保存的⽤⼾信息(姓名、性别、年龄、学历等

等)、⽹⻚⾥⾁眼可以看到的信息(⽂字、图⽚、视频等等),这些都是数据

结构:当我们想要使⽤⼤量使⽤同⼀类型的数据时,通过⼿动定义⼤量的独⽴的变量对于程序来说,可读性 ⾮常差,我们可以借助数组这样的数据结构将⼤量的数据组织在⼀起,结构也可以理解为组织数据的⽅式。

概念: 数据结构是计算机存储、组织数据的⽅式。 数据结构是指相互之间存在⼀种或多种特定关系 的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么⽅式构成,以及数据元素之间呈现的结构。

总结:

1)能够存储数据(如顺序表、链表等结构)

2)存储的数据能够方便查找

1.2 为什么需要数据结构

不借助排队的⽅式来管理客⼾,会导致客户就餐感受差、等餐时间⻓、餐厅营业混乱等情况。同理,程序中如果不对数据进⾏管理,可能会导致数据丢失、操作数据困难、野指针等情况。

通过数据结构,能够有效将数据组织和管理在⼀起。按照我们的⽅式任意对数据进⾏增删改查等操作。

最基础的数据结构: 数组。

3a72b7b01332d5e2b97f2e29448d193c_5c0bf57540d244e0bef601153ae84aca.png

有了数组,为什么还要学习其他的数据结构?

因为最基础的数据结构能够提供的操作已经不能完全满⾜复杂算法实现。


二、顺序表的概念及结构

2.1 线性表

线性表( linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使⽤的数据结构,是具有部分相同特性的⼀类数据结构的集合, 常见的线性表:顺序表、链表、栈、队列、字符串.. .

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

顺序表的逻辑结构是线性的,物理结构也是线性的

链表的逻辑结构是线性的,物理结构不一定是线性的

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

逻辑结构:从一个节点能找到第二个节点,第二个能找到第三个,像线一样串在一起排列

物理结构:内存存储上,是一个挨着一个,内存地址是连续的

2.2  顺序表分类

2.2.1 顺序表和数组的区别

 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝

2.2.2  顺序表分类

1 .静态顺序表

概念:使⽤定⻓数组存储元素

静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费

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

2. 动态顺序表

概念:使用动态数组储存元素


动态顺序表的优点:按需申请空间,不造成浪费

//动态顺序表
struct Seqlist
{
int* a;//动态数组
int size;//有效数据个数
int capacity;//空间大小
}


三、实现顺序表

3.1 创建+初始化+销毁顺序表

3.1.1 SeqList.h

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
typedef int  SLDateType;
typedef struct SeqList
{
  SLDateType* a;
  int size;//空间有效数据
  int capacity;//空间大小
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestory(SL* ps);

3.1.2 SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
void SLInit(SL* ps)
{
  ps->a = NULL;
  ps->size = ps->capacity = 0;
}
void SLDestory(SL* ps)
{
  if (ps->a)
    free(ps->a);
  ps->a = NULL;
  ps->size = ps->capacity = 0;
}


3.1.2 text.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include<stdio.h>
int main()
{
  SL ps;
  SLInit(& ps);
  SLDestroy(&ps);
  return 0;
}

3.2    尾插+头插+打印顺序表

思路:尾插、头插之前需要判断空间是否足够,不够的话以2倍或1.5倍申请空间


(注:若当前空间向后申请空间,发现没有足够的连续空间可以开辟,那么就重新在堆区的另一个地方申请足够的连续空间,并将数据拷贝到新空间,释放原来的顺序表空间,实际上这位就是realloc的操作)


当空间足够后,尾插即在下标为size的数组元素空间插入数据即可


头插即将原来数据都往后移一位,在下标为0的数组元素空间插入数据即可


3.2.1 SeqList.h

//尾插和头插
void SLPushBack(SL* ps, SLDateType x);
void SLPushFront(SL* ps, SLDateType x);
void SLPrint(SL* ps);

3.2.2 SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include<stdio.h>
int main()
{
  SL ps;
  SLInit(& ps);
  SLPushBack(&ps, 1);
  SLPushBack(&ps, 2);
  SLPushBack(&ps, 3);
  SLPushBack(&ps, 4);
  SLPrint(&ps);//1,2,3,4
  SLPushFront(&ps, 5);
  SLPrint(&ps);//5,1,2,3,4
  return 0;
}

3.2.3 text.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include<stdio.h>
int main()
{
  SL ps;
  SLInit(& ps);
  SLPushBack(&ps, 1);
  SLPushBack(&ps, 2);
  SLPushBack(&ps, 3);
  SLPushBack(&ps, 4);
  SLPrint(&ps);//1,2,3,4
  SLPushFront(&ps, 5);
  SLPrint(&ps);//5,1,2,3,4
  return 0;
}

代码结果


image.png


3.3   头删+尾删

思路:在头删和尾删之前,需要判断顺序表是否有有效数据


头删:将后面的数据往前移一位,覆盖第一位数据即可


尾删:将有效数据个数减少一位即可


3.3.1 SeqList.h

//头删和尾删
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

3.3.2 SeqList.c

bool SLIsEmpty(SL * ps)//若返回值为假,则有数据,反之,则无
{
  assert(ps);
  return ps->size == 0;
}
void SLPopBack(SL* ps)
{
  assert(ps);
  //还需要判断是否有数据
  assert(!SLIsEmpty(ps));
  ps->size--;
}
void SLPopFront(SL* ps)
{
  assert(ps);
  //还需要判断是否有数据
  assert(!SLIsEmpty(ps));
  for (size_t i = 0; i < ps->size-1; i++)
  {
    ps->a[i] = ps->a[i + 1];
  }
  ps->size--;
}


3.3.3 text.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include<stdio.h>
int main()
{
  SL ps;
  SLInit(& ps);
  SLPushBack(&ps, 1);
  SLPushBack(&ps, 2);
  SLPushBack(&ps, 3);
  SLPushBack(&ps, 4);
  SLPrint(&ps);//1,2,3,4
  SLPushFront(&ps, 5);
  SLPrint(&ps);//5,1,2,3,4
  SLPopBack(& ps); //5, 1, 2, 3
  SLPrint(&ps);
  SLPopFront(&ps); //1, 2, 3
  SLPrint(&ps);
  return 0;
}

3.4  在指定位置之前插入数据+删除指定位置

注:我实现的这个指定位置,指的是顺序表的值,而不是顺序表下标位置


如果指定位置为下标位置,那么就更好实现了


3.4.1 SeqList.h

//在指定位置之前插入
void SLInsert(SL* ps, SLDateType pos, SLDateType x);
//删除指定位置
void SLDel(SL* ps, SLDateType pos);
int SLFind(SL* ps, SLDateType pos);

3.4.2 SeqList.c

int SLFind(SL* ps, SLDateType pos)
{
  assert(ps);
  for (size_t i = 0; i < ps->size; i++)
  {
    if (ps->a[i] == pos)
    {
      return i;
    }
  }
  return -1;
}
// 在指定位置之前插入
void SLInsert(SL* ps, SLDateType  pos, SLDateType x)
{
  assert(ps);
  SLCheckCapacity(ps);
  //防止越界访问
  int ret = SLFind(ps, pos);
  if (ret < 0)
  {
    printf("没有该位置\n");
    return;
  }
  assert(ret >= 0 && ret<= ps->size);//端点位置为头插和尾插
  for (size_t i = ps->size; i >ret; i--)
  {
    ps->a[i] = ps->a[i - 1];
  }
  ps->a[ret] = x;
  ps->size++;
}
//删除指定位置
void SLDel(SL* ps, SLDateType)
{
  assert(ps);
  assert(!SLIsEmpty(ps));
  int ret = SLFind(ps, pos);
  if (ret < 0)
  {
    printf("没有该位置\n");
    return;
  }
  assert(ret>= 0 && ret < ps->size);//端点位置为头删和尾删
  for (size_t i = pos; i < ps->size-1; i++)
  {
    ps->a[i] = ps->a[i + 1];
  }
  ps->size--;
}

3.4.3 text.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include<stdio.h>
int main()
{
  SL ps;
  SLInit(& ps);
  SLPushBack(&ps, 1);
  SLPushBack(&ps, 2);
  SLPushBack(&ps, 3);
  SLPushBack(&ps, 4);
  SLPrint(&ps);//1,2,3,4
  //SLPushFront(&ps, 5);
  //SLPrint(&ps);//5,1,2,3,4
  //SLPopBack(& ps); //5, 1, 2, 3
  //SLPrint(&ps);
  SLInsert(&ps,2, 5);
  //SLPopFront(&ps); //1, 2, 3
  SLPrint(&ps);//1,5,2,3,4
  SLDel(&ps, 2);
  SLPrint(&ps);
  return 0;
}


代码运行:

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