【数据结构】动态顺序表的实现

news/2024/10/18 3:29:06/

1.什么是数据结构

数据结构就是把数据元素按照一定的关系组织起来的集合,用来组织和存储数据。通过数据结构,能够有效的将数据组织和管理在一起,按照我们的方式任意对数据进行增删查改等操作。

2.数据结构的分类 

数据结构大概可分为逻辑结构物理结构两大类 。

2.1逻辑结构 

逻辑结构:是从具体问题中抽象出来的模型,是抽象意义的结构。

  • 集合结构:结构中数据元素除了同属于一个集合外,它们之间没有任何关系
  • 线性结构:结构中数据元素之间存在一一对应的关系
  • 树形结构:结构中数据元素之间存在一对多的层次关系
  • 图形结构:结构中数据元素是多对多的关系

2.2物理结构 

物理结构:逻辑结构在计算机中真正的表示方式(又称映像)。

常见的物理结构(存储结构)有顺序存储链式存储索引存储,以及散列存储

  • 顺序存储结构:把数据元素放到地址连续的内存单元里面,其数据间的逻辑关系和物理关系是一致的,比如我们常用的数组就是顺序存储结构。
  • 链式存储结构:是把数据元素存放在任意的存储单元里面,这组存储单元可以是连续的,也可以是不连续的。此时,数据间的物理关系不能反映其逻辑关系。所以每一数据元素均使用一个结点来存储,不仅需要存储数据元素,而且还要存储数据元素之间的逻辑关系(将结点分为两部分,一部分存储数据元素本身,称为数据域;一部分存储下一个结点的地址,称为指针域。
  • 索引存储结构:在索引存储结构中,不仅需要存储所有数据元素(称为主数据表),还需要建立附加的索引表。每个数据元素都由一个唯一的关键字来标识,由该关键字和对应的数据元素的地址构成一个索引项,存入索引表。
  • 散列(哈希)存储结构:散列存储结构是指依据数据元素的关键字,通过事先设计好的哈希函数计算出一个值,再将其作为该数据的存储地址。

2.3总结 


最基础的数据结构数组

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

假定数组有10个空间,已经使用了5个,向数组中插入数据步骤:

求数组的有效数据个数,向下标为数据有效个数的位置插入数据。(注意:这里要判断数组是否满了)

假设数据量非常庞大,频繁的获取数组有效数据个数会影响程序执行效率。

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


3.线性表

线性表(linear list)指的是具有部分相同特性的一类数据结构的集合。

线性表的逻辑结构属于线性结构,采用顺序存储结构为顺序表,采用链式存储结构为线性链表顺序表在C语言中一般使用数组去实现,链表使用结构体去实现


3.1顺序表

顺序表的底层结构是数组,通过对数组的封装,实现了常用的增删改查等接口。

3.2顺序表的分类

静态顺序表

概念:使用定长数组存储元素

//静态顺序表
typedef int SLDATATYPE;
#define N 100
typedef struct SeqList
{SLDATATYPE arr[N];//定长数组int size;//顺序表当前有效数据个数
}SL;

静态顺序表缺陷静态顺序表的长度是固定的,因此数组满了需要手动更改N,空间给少了不够用,给多了造成空间浪费。

动态顺序表

//动态顺序表——按需申请  可增容
typedef int SLDATATYPE;
typedef struct SeqList
{SLDATATYPE* arr;//指向动态开辟的数组int size;//顺序表当前有效数据个数int capacity;//记录当前空间大小
}SL;

3.3动态顺序表的实现

3.3.1顺序表的初始化

void SLInit(SL *ps)//注意:这里不可以写成void SLInit(SL ps)//会报错:使用了未初始化的局部变量!这是值传递,对形参的修改不影响实参。要传地址
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

3.3.2顺序表的销毁

顺序表的销毁
void SLDestory(SL* ps)
{if (ps->arr){free(ps->arr);//先释放空间,然后置空}ps->arr = NULL;ps->size = ps->capacity = 0;
}

3.3.3顺序表的插入

尾插

注意:插入数据之前先看空间够不够。初始化后空间容量为0,插入数据之前先申请空间,也可能空间满了,有效数据个数等于空间容量了,也要申请空间。

容量检查函数

void SLCheckCapacity(SL*ps)
{//插入数据之前先看空间够不够if (ps->capacity == ps->size){//申请空间		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//三目表达式SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * 2 * sizeof(SLDataType));//要申请多大空间//若要频繁的增容,则会造成程序的运行效率大大降低,增容通常来说是成倍数的增加,一般是2或者3倍//realloc申请空间失败返回空指针,所以再造一个临时的指针tmpif (tmp == NULL){perror("realloc");exit(1);//直接退出程序}//空间申请成功ps->arr = tmp;ps->capacity = newcapacity;}
}

尾插实现 

void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;//增加一个数据,有效数据个数+1/*ps->arr[ps->size] = x;++ps->size;*/
}

头插

void SLPushFront(SL* ps, SLDataType x)
{assert(ps);	SLCheckCapacity(ps);//先让顺序表中已有的数据整体往后挪动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];//最后一次ps->arr[1]=ps->arr[0]}ps->arr[0] = x;ps->size++;
}

3.3.4顺序表的删除

尾删

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//判断顺序表是否为空,为空不能执行删除操作//顺序表不为空--ps->size;
}

注意:被删除的数据空间不需要置为0,没有意义,下次访问这块空间时,新的数据会覆盖掉。也不能释放空间,因为free只能从开辟的空间的首地址处释放,不能释放其他地方的空间。


头删

void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//数据整体往前挪动一位for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];//最后一次ps->arr[size-2] = ps->arr[size-1]}ps->size--;
}

3.3.5在指定位置插入数据

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//让pos及之后的数据整体向后挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//最后一次ps->arr[pos+1]=ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}

3.3.6删除指定位置的数据

void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];//最后一次ps->arr[size-2]=ps->arr[size-1]}ps->size--;
}

3.3.7顺序表的查找

int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] ==x){//找到了!return i;}}//没有找到!return -1;
}


http://www.ppmy.cn/news/1514812.html

相关文章

ucharts图表滚动

背景&#xff1a; 使用ucharts绘制折线图&#xff0c;当数据项多的时候&#xff0c;横坐标显示的文字会重合&#xff0c;故想到滑动 项目代码使用的是原生的代码&#xff0c;而非ucharts的组件&#xff1a; <template><view><canvas canvas-id"chartsLi…

银河麒麟V10如何安装本地deb软件包?(以安装wps为例)

银河麒麟V10如何安装本地deb软件包&#xff1f;&#xff08;以安装wps为例&#xff09; 一、准备二、安装三、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在银河麒麟V10中安装本地.deb软件包&#xff0c;虽然apt主要用于管理仓库中…

java整合Redis

Jedis Jedis是Redis官方推荐的Java连接开发工具&#xff0c;是一个用于连接和操作Redis数据库的Java客户端库。它提供了一系列的方法来操作Redis的键值存储、列表、哈希、集合和有序集合等数据结构。要在Java开发中使用好Redis中间件&#xff0c;必须对Jedis熟悉才能写成漂亮的…

Linux网络环境搭建,开发板网线直连电脑网口,电脑WIFI上网

开发板网线直连电脑网口&#xff08;电脑自带&#xff0c;一般有PCI&#xff0c;不是USB网卡&#xff09;&#xff0c;电脑WIFI上网 因为电脑是 WiFi 上网&#xff0c;所以需要添加一个网络适配器并设置成 NAT 模式&#xff0c;供虚拟机上网。 设置双网卡&#xff0c;注意双网卡…

国产3A游戏《黑神话悟空》中AI绘画技术的运用与探索

导语&#xff1a;近年来&#xff0c;我国游戏产业不断发展&#xff0c;越来越多的国产游戏开始尝试运用AI技术&#xff0c;以提升游戏品质。其中&#xff0c;国产3A游戏《黑神话悟空》便在原画设计过程中&#xff0c;巧妙地运用了AI绘画技术。本文将带你了解《黑神话悟空》如何…

C语言试题(含答案解析)

单选 1.下面C程序的运行结果为&#xff08;&#xff09; int main(void) {printf("%d", B < A);return 0; }A.编译错误 B.1 C.0 D.运行错误 A’的ascii码值为65&#xff0c;‘B’的ascii码值为66&#xff0c;‘B’<‘A’是不成立的&#xff0c;返回0&#xf…

浅拷贝和深拷贝(图文详解)

前端面试中&#xff0c;面试官经常会提到关于浅拷贝和深拷贝的问题。但是我总是理解于它的表面&#xff0c;面试中再深挖一点就会卡壳&#xff0c;我想把我的理解写下来&#xff0c;希望可以帮助到大家&#xff0c;如果有错误的地方希望大家可以指正&#xff0c;以免误导~ 看这…

Android 自适应屏幕技术

layout自适应屏幕大小Android手机屏幕大小不一,有480x320,640x360,800x480.怎样才能让App自动适应不同的屏幕呢? 其实很简单,只需要在res目录下创建不同的layout文件夹,比如:layout-640x360,layout-800x480,所有的layout文件在编译之后都会写入R.java里,而系统会根据…