当前位置: 首页 > news >正文

数据结构 02(线性:顺序表)

目录

线性表

顺序表

概念与结构

动态顺序表的实现

头文件的创建

顺序表初始化

顺序表的扩容

尾插功能

头插功能

尾删功能

头删功能

查找功能

任意位置前插入

任意位置前删除

销毁

动态顺序表整体呈现

SeqList.h

SeqList.c


线性表

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

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

顺序表

概念与结构

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

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

分类:分为静态顺序表和动态顺序表(常用)。

动态顺序表的实现

头文件的创建

我们要在头文件中完成顺序表的创建和头文件与函数的声明。

typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;int capacity;
}SL;

这是头文件的包含和顺序表的创建。

这是对函数的声明,以上函数我们都会讲到。

顺序表初始化

首先我们要在源文件中包含刚刚我们创建的头文件。

然后对顺序表进行初始化。

void SLInit(SL* ps)//初始化
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

顺序表的扩容

现在我们的顺序表里面什么都没有,我们要扩大我们的空间。或者当我们的顺序表空间满了的时候,我们也要扩大我们的空间。

所以我们要先写好函数对顺序表进行扩容。

扩容函数中我们需要使用realloc函数额外申请空间。

注意:进行扩容操作时请用临时变量,防止发生问题造成不可逆的伤害。

void SLCheckCapacity(SL* ps)//扩容
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}

尾插功能

实现尾插功能很简单,size刚好是数组最后一个元素的后一个下标,确定指针的安全后直接令arr[size]等于x就完成了。

void SLPushBack(SL* ps,SLDataType x)//尾插
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}

头插功能

头插功能比尾插复杂一点点,需要让数组中的元素整体后移一个位置,让arr[0]空缺起来实现x的插入。

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[0] = x;++ps->size;
}

尾删功能

尾删很简单,直接让size减一就好了。

void SLPopBack(SL* ps)//尾删
{assert(ps && ps->size);--ps->size;
}

头删功能

头删也很简单,就让后面的元素把前面的元素一一覆盖就好了。

void SLPopFront(SL* ps)//头删
{assert(ps && ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}--ps->size;
}

查找功能

遍历数组查找元素,找到返回下标,没找到返回-1。

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

任意位置前插入

这是建立在头插的基础上的,让pos后的元素一一往后移一个位置把pos空出来实现插入。

void SLInsert(SL* ps, int pos, SLDataType x)//任意位置前插入
{assert(ps);assert(pos >= 0 && pos <= ps->size);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;++ps->size;
}

任意位置前删除

和头删很相似,让pos后的元素一一往前移一个位置覆盖pos。

void SLErase(SL* ps, int pos)//任意位置前删除
{assert(ps && ps->size);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}--ps->size;
}

销毁

结束后一定要进行函数的销毁操作。

void SLDesTroy(SL* ps)//销毁
{if (ps->arr)free(ps->arr);ps->arr = NULL;ps->size = ps->capacity = 0;
}

动态顺序表整体呈现

SeqList.h

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;int capacity;
}SL;void SLInit(SL* ps);
void SLDesTroy(SL* ps);
void SListPrint(SL s);
void SLCheckCapacity(SL* ps);
void SLPushBack(SL* ps,SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"void SLInit(SL* ps)//初始化
{ps->arr = NULL;ps->size = ps->capacity = 0;
}void SListPrint(SL s)//打印
{for (int i = 0; i < s.size; i++){printf("%d ", s.arr[i]);}printf("\n");
}void SLCheckCapacity(SL* ps)//扩容
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}void SLPushBack(SL* ps,SLDataType x)//尾插
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}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[0] = x;++ps->size;
}void SLPopBack(SL* ps)//尾删
{assert(ps && ps->size);--ps->size;
}void SLPopFront(SL* ps)//头删
{assert(ps && ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}--ps->size;
}int SLFind(SL* ps, SLDataType x)//查找
{for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x)return i;}return -1;
}void SLInsert(SL* ps, int pos, SLDataType x)//任意位置前插入
{assert(ps);assert(pos >= 0 && pos <= ps->size);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;++ps->size;
}void SLErase(SL* ps, int pos)//任意位置前删除
{assert(ps && ps->size);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}--ps->size;
}void SLDesTroy(SL* ps)//销毁
{if (ps->arr)free(ps->arr);ps->arr = NULL;ps->size = ps->capacity = 0;
}
http://www.dtcms.com/a/356675.html

相关文章:

  • 第四章 Vue3 + Three.js 实战:GLTF 模型加载与交互完整方案
  • Go初级之五:结构体与方法
  • 二手奢侈品拍照估价上门快递回收小程序开发
  • 前端如何使用canvas实现截图
  • 【前端教程】从零开始学JavaScript交互:7个经典事件处理案例解析
  • 嵌入式Linux驱动开发 - DTS LED驱动
  • 拼多多商品信息批量获取及开放API接口调用指南
  • 【面试场景题】dubbo可以使用自定义的序列化协议吗
  • 音视频学习(五十九):H264中的SPS
  • Kubernetes: 解构Karpenter NodePool, 云原生时代的弹性节点管理艺术
  • 【K8s】整体认识K8s之集群的pod之间的通信
  • LSM6DS3姿态芯片和LIS2MD磁力计芯片数据读取(stm32)
  • 千年智造,一触即发 耐达讯自动化Profibus集线器如何让HMI触摸屏在工业4.0中“点石成金“?
  • 嵌入式Linux驱动开发 - 并发控制机制
  • 【视频讲解】R语言海七鳃鳗性别比分析:JAGS贝叶斯分层逻辑回归MCMC采样模型应用
  • 嵌入式Linux驱动开发 - 新字符设备LED驱动
  • Go Vendor 和 Go Modules:管理和扩展依赖的最佳实践
  • Redis vs Elasticsearch:核心区别深度解析
  • Vue 项目首屏加载速度优化
  • Mysql系列--11、使用c/c++访问mysql服务
  • ViennaCL并行异构库介绍和使用
  • Pinterest自动化 “Pin“得高效
  • SpringMvc下
  • Oracle SQL 性能调优的基石:深入解读与驾驭执行计划
  • 商家协同生态下的复购革命:跨店收益如何激活12%增量消费
  • 【新启航】3D 逆向抄数的工具技术与核心能力:基于点云处理的扫描设备操作及模型重建方法论
  • 【活动回顾】“智驱未来,智领安全” AI+汽车质量与安全论坛
  • OpenEuler部署LoganaLyzer
  • 【开题答辩全过程】以 基于SpringBootVue的智能敬老院管理系统为例,包含答辩的问题和答案
  • 黑芝麻智能与云深处科技达成战略合作,共推具身智能平台全球市场应用