【数据结构之C语言实现动态顺序表】

引    入:

  在讲顺序表之前得先了解线性表是什么?

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

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

顺      序     表

1.顺序表的概念

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

组存储。(顺序表的底层结构就是数组)顺序表就相当于在数组的基础上进行了“装修”,即

增删查数据的操作。

2.顺序表的结构

基于数组进行实现顺序表。实现时会有两种顺序表结构:静态顺序表和动态顺序表。

2.1定义静态顺序表的结构:

#define N 100
typedef struct SeqList
{int arr[N];int size;//有效的数据个数
}SL;

当然我们不肯能只对整型数据进行操作,我们还可以对其他的数据类型进行操作。因此我们需要在这里对类型进行重命名。typedef int SLDatatype;

即:

#define N 100
typedef int SLDatatype;
struct Seqlist
{SLDatatype arr[N];int size;//有效的数据个数
}SL;

总结:   我们可以很清楚地发现,静态顺序表的一个巨大弊端,那么就是数组的长度是有限

,但我们随机插入的数据的数量未必是在给定的范围之内,这会造成空间不够。当然有些

人可能会觉得给数组一个很大的长度就可以了呀,但如果我们在某段时间内不需要那么大的

长度,那就会造成空间的浪费

2.2定义动态顺序表的结构

结合上面静态顺序表的结构,那么实现动态顺序表的目的就是解决这一弊端。我们前面的C

语言部分学习的动态内存管理的知识就可以用到这里来了。在这里我们需要涉及到动态的内

存扩容,而不是直接向内存申请空间,所以在后面的实现中,我们需要用到realloc函数

在这里我们定义动态顺序表的时候需要定义三个部分,用指针定义一个所要操作的数据类型

的指针,再定义标记数据个数的和空间大小的两个整型变量。即:

typedef int SLDatatype;
typedef struct SeqList
{SLDatatype* arr;int size;//记录当前顺序表中有效的元素个数int capacity;//记录顺序表的空间大小
}SL;

那么我们在实现顺序表的时候就要实现动态顺序表,动态顺序表相较于静态顺序表更好,弥补了静

态顺序表的不足!

接下来就带着大家来实现一下动态顺序表的以下相关操作。

在这之前我们将头文件以及函数功能功能实现的声明放在SeqList.h中,将函数的实现部分放

在SeqList.c中,再建立一个test.c函数功能的测试部分。

1.  SeqList.h


//顺序表的函数的声明部分//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDestroy(SL* ps);//顺序表的插入
//顺序表的尾插
void SLPushBack(SL* ps, SLDatatype x);
//顺序表的头插
void SLPushFront(SL* ps, SLDatatype x);//顺序表的删除
//顺序表的尾删
void SLPopBack(SL* ps);
//顺序表的头删
void SLPopFront(SL* ps);//顺序表指定位置的操作
//指定位置之前插入数据
void SLInsertBefore(SL* ps, int pos, SLDatatype x);
//指定位置的删除数据
void SLErase(SL* ps, int pos);//顺序表的数据的查找
int SLFind(SL* ps, SLDatatype x);

2.函数功能的实现部分  SeqList.c

(需要包含上面的自定义的头文件----#include "SeqList")

2.1  顺序表的初始化和销毁

//顺序表的初始化
void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}

2.2 顺序表的数据的插入


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

       在进行顺序的插入之前我们需要先对顺序表的空间够不够进行检查(封装成函数),如果不

能够我们就需要通过realloc函数对顺序表的空间进行二倍扩容,当然如果刚开始的空间大小

为0是我们就需要给定一定的空间大小(在这里我给的是4)。

头插和尾插
//顺序表的尾插
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);//数据整体向后移动1位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}

       在进行数据插入之前先进行对指针进行判空,再进行空间大小的检查。尾插就直接在

size的位置插入数据,随后再进行size++操作;头插就先将数据整体向后移动一位,然后再

进行数据插入,最后进行size++。

2.3顺序表的数据的删除

//顺序表的删除
//顺序表的尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size > 0);ps->size--;
}
//顺序表的头删
void SLPopFront(SL* ps)
{assert(ps && ps->size > 0);//数据整体向前移动for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

对于顺序表的尾删,就直接将size--;对于顺序表的头删整体向前移动一位,然后size--。

2.4顺序表中数据的查找

//顺序表的数据的查找
int SLFind(SL* ps, SLDatatype x)
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x)return i;}return -1;
}

先进行地址判空,再进行对有效数据个数进行检查看是否大于0,随后进行遍历查找判断是否

为顺序表中数据,如果是就返回下标,如果不是就返回无效下标(我这里找不到的时候让返

回-1)。

2.5顺序表中指定位置的操作

//顺序表指定位置的操作
//指定位置之前插入数据
void SLInsertBefore(SL* ps, int pos, SLDatatype x)
{assert(ps);assert(pos >= 0&& pos <= ps->size);SLCheckCapacity(ps);//将pos 以及pos之后的数据整体向后移动一位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);assert( pos >= 0&&pos<ps->size);//pos之后的数据整体向前移动一位for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

在指定位置之前插入数据先进行pos的范围判断,pos大于等于0,小于等于size,随后将pos及

pos之后数据整体先向后移动一位,进行插入数据,size++;删除pos 位置的数据先进行pos

的范围判断,pos大于等于0,小于size-1,然后将pos之后的数据整体向前移动一位,size--.

 

3.函数的测试部分

#include "SeqList.h"void SLPrint(SL sl)
{for (int i = 0; i < sl.size; i++){printf("%d ", sl.arr[i]);}printf("\n");
}
void test()
{SL sl;SLInit(&sl);SLPushBack(&sl, 13);SLPushBack(&sl, 22);SLPushBack(&sl, 34);SLPushBack(&sl, 45);SLPrint(sl);/*SLPopBack(&sl);SLPrint(sl);SLPopFront(&sl);SLPrint(sl);*/int ret=SLFind(&sl, 45);if (ret < 0)printf("找不到该元素\n");elseprintf("找到了,该元素的下标为:%d\n", ret);//SLInsertBefore(&sl, ret, 99);SLErase(&sl, ret);SLPrint(sl);printf("size:%d\n", sl.size);SLPushBack(&sl, 99);SLPrint(sl);printf("size:%d\n", sl.size);SLDestroy(&sl);SLPrint(sl);
}
int main()
{test();return 0;
}

数据结构这块需要我们多加练习,多多画图思考,理解掌握!!!

如有错误,还望指出!!!

关注博主,优质内容不断更新!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Meta 发布地表最大、最强大模型 Llama 3.1

最近这一两周看到不少互联网公司都已经开始秋招提前批了。不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解…

【iOS】暑期第一周——ZARA app仿写

目录 前言无限轮播图分栏控件和滚动视图自定义cell遇到的问题调整图标大小单元格附件视图设置 总结 前言 暑假学习的第一周任务是对ZARA app进行仿写&#xff0c;充分运用之前学习的Objective-C语言和UI控件。我在编写demo的过程中遇到了一些问题&#xff0c;特写该博客作为学习…

LLM与搜索推荐

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

VScode连接服务器免密登录

1、生成 SSH 密钥对 打开终端并输入以下命令生成 SSH 密钥对&#xff1a; 直接搜索 cmd&#xff0c;然后输入&#xff1a; ssh-keygen -t rsa -b 4096 一直回车就好了 这时公钥存储在/Users/你的用户名/.ssh/id_rsa.pub文件里&#xff0c;私钥存储在/Users/你的用户名/.ss…

简单的数据结构:栈

1.栈的基本概念 1.1栈的定义 栈是一种线性表&#xff0c;只能在一端进行数据的插入或删除&#xff0c;可以用数组或链表来实现&#xff0c;这里以数组为例进行说明 栈顶 &#xff1a;数据出入的那一端&#xff0c;通常用Top表示 栈底 :相对于栈顶的另一端&#xff0c;也是固…

黑马头条vue2.0项目实战(一)——项目初始化

1. 图标素材&#xff08;iconfont简介&#xff09; 制作字体图标的工具有很多&#xff0c;推荐使用&#xff1a;iconfont-阿里巴巴矢量图标库。 注册账户 创建项目 可以根据项目自定义 class 前缀 上传图标到项目 生成链接&#xff0c;复制 css 代码&#xff0c;在项目中使用…

【知识梳理】Shell的变量计算

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 Shell中有很多变量的计算&#xff0c;会用到多种运算符。例如这几种&#xff1a; 1. Shell中常见的算术运算符 运算符意义&…

github-page静态网页将字符串写入github库中文本文档

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 问题描述 github-page静态…

Natutre Methods|单细胞+空间转录,值得去复现的开源单细胞分析pipeline

肺癌是全球第二大最常见的癌症&#xff0c;也是癌症相关死亡的主要原因。肿瘤生态系统具有多种免疫细胞类型。尤其是髓系细胞&#xff0c;髓系细胞普遍存在&#xff0c;并且在促进疾病方面发挥着众所周知的作用。该篇通过单细胞和空间转录组学分析了 25 名未经治疗的腺癌和鳞状…

网络模型优化——从参数向量到性能提升的最优化之旅

网络模型优化——从参数向量到性能提升的最优化之旅 网络模型优化的核心作用 组件/步骤描述参数向量网络模型中的可学习部分&#xff0c;决定了模型的输出泛函最优化通过调整参数向量以最小化或最大化某个目标函数的过程目标函数用于评估模型性能的指标&#xff0c;如损失函数…

【初阶数据结构篇】顺序表的实现(赋源码)

文章目录 本篇代码位置顺序表和链表1.线性表2.顺序表2.1 概念与结构2.2分类2.2.1 静态顺序表2.2.2 动态顺序表 2.3 动态顺序表的实现2.3.1动态顺序表的初始化和销毁及打印2.3.2动态顺序表的插入动态顺序表的尾插动态顺序表的头插动态顺序表的在指定位置插入数据 2.3.3动态顺序表…

区块链——hardhat使用

一、引入hardhat yarn add --dev hardhat // 引入验证合约的插件 yarn add --dev nomicfoundation/hardhat-verify 二、创建hardhat项目 yarn hardhat 三、编写我们的合约 四、编译我们的合约 yarn hardhat compile 五、编写脚本部署合约以及验证合约 // 获取hardhat环境对象 c…

Python操作Redis指南

文本主要介绍使用Python中的redis-py库来操作Redis数据库&#xff0c;包括安装必要的包、建立和关闭连接、执行增删改查操作以及处理可能的异常。这些操作将在Python应用程序中与Redis数据库进行有效的交互。 一. 简介和包的安装 Redis是一种开源的内存数据结构存储&#xff…

Jmeter混合压测(2407)

一 压测需求&#xff1a; 电商作为服务端&#xff0c;至少需要满足并发量,QPS:100/s,TPS:20/s。例如场景&#xff1a; 电商交易中&#xff0c;商品图片请求量最多&#xff0c;电商服务端需要满足并发请求查询图片信息。各家可能会并发请求同一家电商商品、订单等内容。 二 压…

代码随想录算法训练营day7 | 454.四数相加II、383.赎金信、15.三数之和、18.四数之和

文章目录 454.四数相加II思路 383.赎金信思路 15.三数之和思路剪枝去重 18.四数之和思路剪枝去重复习&#xff1a;C中的类型转换方法 总结 今天是哈希表专题的第二天 废话不多说&#xff0c;直接上题目 454.四数相加II 建议&#xff1a;本题是 使用map 巧妙解决的问题&#x…

HarmonyOS(45) 控件拖动或者拖拽PanGesture

PanGesture实现控件拖动的效果&#xff0c;通过拖动的坐标位置调用position或者translate方法来更新UI的位置。效果见下图&#xff1a; 具体代码如下&#xff1a; // xxx.ets Entry Component struct PanGestureExample {State offsetX: number 0State offsetY: number 0pos…

【AI学习指南】轻量级模型-用 Ollama 轻松玩转本地大模型

目录 探索 最小的AI模型 发现 其他轻量级模型 用 Ollama 轻松玩转本地大模型 本地大模型 Ollama 快速上手 安装 手动安装 下载ollama二进制文件 添加 Ollama 作为启动服务(推荐) 安装 CUDA 驱动程序(可选 - 适用于 Nvidia GPU) 安装 ROCm(可选 - 对于 Radeo…

Typesript的type和interface的异同?

详解TypeScript中type与interface的区别_javascript技巧_脚本之家 一、相同的地方 1、都可以用来定义对象&#xff0c;描述函数 我们在用typescript开发的时候经常要用到数据类型定义&#xff0c;比如我们写一个接口或者函数的时候定义传参数据类型及字段等。这样子方便知道这…

代码随想录day21 二叉树最后一天 || 669修剪二叉树 108将有序数组转变为平衡搜索二叉树 538把搜索二叉树变为累加二叉树

669修剪二叉树 力扣题目链接 题目描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果…

K8s 核心组件——API Server

1. Kubernetes API Server 概述 1.1 基本概念 Kubernetes API Server&#xff08;API Server&#xff09;是 Kubernetes 的核心组件之一&#xff0c;负责暴露 Kubernetes API 给用户和客户端&#xff0c;接收和处理来自客户端的请求&#xff0c;并将其存储到 etcd 中。Kubern…