C语言线性表的实现(详解)

news2024/11/26 19:25:17

数据结构之线性表

线性表的基本概念:线性表是由0个或者多个数据元素的有限序列
特性是:
​ 1:数据元素之间都是有顺序的
​ 2:数据元素的个数是有限的,
​ 3:数据元素的类型是相同的
​ 性质是:
a0是线性表的第一个元素,只有一个后继,an为线性表的最后一个元素,只有一个前驱
​ 除去a0和an外的其他元素ai,既有前驱也有后继线性表可以逐项访问的顺序存取

线性表的顺序存储结构:指的是用一组地址连续的存储单元依次存储线性表中的数据元素
1: 当插入一个新的元素时,发现内存空间不足申请一块更大的内存空间
2: 将原空间的数据拷贝到新的内存空间
3: 释放旧的内存空间
4: 把元素放入新的空间

1: 动态的内存增加,将存放数据的内存放到堆上(堆的内存空间比较大,不容易发生溢出)
2: 动态数组,如果是5个元素,申请内存,拷贝数据,释放内存,插入第7个数据?
3: capacity容量表示在这一块的内存空间中可以存放多少元素
4: size的概念记录当前数组中具体的内存个数

在这里插入图片描述
程序的头部文件
在这里插入图片描述具体头文件的代码如下所示

 #ifndef DYNAMIC_ARRAY_H
#define DYNAMIC_ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>


/*
	  线性表的基本概念:线性表是由0个或者多个数据元素的有限序列
	  特性是:1:数据元素之间都是有顺序的,2:数据元素的个数是有限的,3:数据元素的类型是相同的
	  性质:a0是线性表的第一个元素,只有一个后继,an为线性表的最后一个元素,只有一个前驱
	  除去a0和an外的其他元素ai,既有前驱也有后继线性表可以逐项访问的顺序存取

	  线性表的顺序存储结构:指的是用一组地址连续的存储单元依次存储线性表中的数据元素
	
	  1: 当插入一个新的元素时,发现内存空间不足申请一块更大的内存空间
	  2: 将原空间的数据拷贝到新的内存空间
	  3: 释放旧的内存空间
	  4: 把元素放入新的空间
	
	  // 动态的内存增加,将存放数据的内存放到堆上
	  // 动态数组,如果是5个元素,申请内存,拷贝数据,释放内存,插入第7个数据?
	  // capacity容量表示在这一块的内存空间中可以存放多少元素
	  // size的概念记录当前数组中具体的内存个数

*/




typedef struct DYNAMICARRAY {
	int* pAddr; // 具体存放数据的地址
	int size;  // 当前有多少个元素
	int capacity;  //当前容器最大容纳多少个元素

}Dynamic_Array;



// 初始化数组
Dynamic_Array* Init_Array();
// 插入
void Push_Back_Array(Dynamic_Array* arr, int value);
// 删除,根据位置对相应的数据进行删除
void Remove_Array(Dynamic_Array* arr, int pos);
// 根据值进行删除
void RemoveByValue_Array(Dynamic_Array* arr, int value);
//查找
int Find_Array(Dynamic_Array* arr, int value);
// 打印输出动态数组当中的值
void Print_Array(Dynamic_Array* arr);
//清空数组
void Clear_Array(Dynamic_Array* arr);
// 获得动态数组容量
int Capacity_Array(Dynamic_Array* arr);
//获得动态数组当前的元素个数
int Size_Array(Dynamic_Array* arr);
int At_Array(Dynamic_Array* arr, int pos);
//释放动态数组的内存
void FreeSpace_Array(Dynamic_Array* arr);


#endif

程序的主文件main
在这里插入图片描述主要文件代码如下所示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <string.h>
#include "DynamicArray.h"



// 初始化数组
Dynamic_Array* Init_Array() {
    // 申请内存
    Dynamic_Array* myArray =(Dynamic_Array*) malloc(sizeof(Dynamic_Array));
    // 初始化
    myArray->size = 0;
    myArray->capacity = 20;
    myArray->pAddr = (int *)malloc(sizeof(int) * myArray->capacity);
    return myArray;

};
// 插入
void Push_Back_Array(Dynamic_Array* arr, int value) {
    if (arr == NULL) {
        return;
    }
    // 判断空间是否足够
    if (arr->size == arr->capacity) {
        // 第一步,申请一块更大的内存空间,新的空间默认就旧空间的2倍
        int* newSpace = (int*)malloc(sizeof(int) * arr->capacity * 2);
        // 第二步,拷贝数据到新的内存空间
        memcpy(newSpace, arr->pAddr, arr->capacity * sizeof(int));
        // 释放旧空间的内存
        free(arr->pAddr);
        // 更新容量
        arr->capacity = arr->capacity * 2;
        arr->pAddr = newSpace;
    }
    //插入新的元素,从尾部插入
    arr->pAddr[arr->size] = value;
    arr->size++;
};

// 删除,根据位置对相应的数据进行删除
void Remove_Array(Dynamic_Array* arr, int pos) {
    if (arr == NULL) {
        return;
    }
    // 判断位置是否有效
    if (pos < 0 || pos >= arr->size) {
        return;
    }
    // 删除元素
    for (int i = pos; i < arr->size - 1; i++) {
        arr->pAddr[i] = arr->pAddr[i + 1];
    }

    arr->size--;

};


// 根据值进行删除
void RemoveByValue_Array(Dynamic_Array* arr, int value) {
    if (arr == NULL) {
        return;
    }
    // 找到值的位置
    int pos = Find_Array(arr,value);
    for (int i = 0; i < arr->size; i++) {
        if (arr->pAddr[i] == value) {
             pos = i;
             break;
        }
    }
    // 根据位置删除
    Remove_Array(arr, pos);

};
//查找
int Find_Array(Dynamic_Array* arr, int value) {
    if (arr == NULL) {
        return -1;
    }
    int pos = -1;
    for (int i = 0; i < arr->size; i++) {
        if (arr->pAddr[i] == value) {
            pos = i;
            break;
        }
    }
    return pos;
};
// 打印
void Print_Array(Dynamic_Array* arr) {
    if (arr == NULL) {
        return;
    }
    // 使用for循环打印输出相关的数据
    for (int i = 0; i < arr->size; i++) {
        printf("%d ", arr->pAddr[i]);

    }
    printf("\n");

};


//清空数组
void Clear_Array(Dynamic_Array* arr) {
    if (arr == NULL) {
        return;
    }
    // pAddr - > 空间
    arr->size = 0;
};
// 获得动态数组容量
int Capacity_Array(Dynamic_Array* arr) {
    if (arr == NULL) {
        return -1;
    }
    return arr->capacity;
};
//获得动态数组当前的元素个数
int Size_Array(Dynamic_Array* arr) {
    if (arr == NULL) {
        return -1;
    }
    return arr->size;
};
int At_Array(Dynamic_Array* arr, int pos) {
    if (arr == NULL) {
        return -1;
    }
    return arr->pAddr[pos];
};
//释放动态数组的内存
void FreeSpace_Array(Dynamic_Array* arr) {
    if (arr == NULL) {
        return;
    }

    // 先释放动态数组内存中里面那块的内存
    if (arr->pAddr != NULL) {
        free(arr->pAddr);
    }
    free(arr);

};


int main(void) {
    Dynamic_Array* myArray = Init_Array();
    // 打印输出数组容量
    printf("数组容量:%d\n", Capacity_Array(myArray));
    printf("数组大小:%d\n", Size_Array(myArray));

    // 插入元素
    for (int i = 0; i < 30; i++) {
        Push_Back_Array(myArray, i);
    }
    printf("数组容量:%d\n", Capacity_Array(myArray));
    printf("数组大小:%d\n", Size_Array(myArray));
    
    // 删除里面的数据
    RemoveByValue_Array(myArray,0);
    RemoveByValue_Array(myArray, 27);
    
    printf("数组容量:%d\n", Capacity_Array(myArray));
    printf("数组大小:%d\n", Size_Array(myArray));
    
    // 查找第五个位置
    int pos = Find_Array(myArray, 5);
    printf("查找5的位置pos:%d  %d\n",pos, At_Array(myArray,pos));


    // 打印
    Print_Array(myArray);
    
    //销毁
    FreeSpace_Array(myArray);system("pause");
    return 0;

}

使用代码模拟线性表实现数据的增,删,改,查(程序的运行结果如下所示)

在这里插入图片描述

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

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

相关文章

二进制编辑器hexedit的安装及使用

Hexedit 同时以 ASCII 和十六进制显示文件 安装 终端输入hexedit回车&#xff0c;如果没安装&#xff0c;会提示让输入 sudo apt-get install hexedit 照着输入命令&#xff0c;安装。安装完成后&#xff0c;cd到一个有二进制文件的目录下&#xff0c;输入hexedit命令回车 再…

激光雷达SLAM(一)------初始激光雷达SLAM

专栏目的及认识激光雷达SLAM 一、专栏目的二、初始激光雷达SLAM1、激光雷达SLAM算法相关知识点2、SLAM常见问题[^2]3、激光雷达SLAM的需求点4、RTK在SLAM中的作用5、激光雷达视觉紧耦合图优化滤波紧耦合 一、专栏目的 大家好&#xff01;介绍一下博主自己&#xff0c;感知算法工…

在云服务器上搭建个人版chatGPT及后端Spring Boot集成chat GPT

原创/朱季谦 本文分成两部分&#xff0c;包括【国内服务器上搭建chat GPT】和【后端Spring Boot集成chat GPT】。 无论是在【国内服务器上搭建chat GPT】和【后端Spring Boot集成chat GPT】&#xff0c;两个方式都需要魔法访问&#xff0c;否则是无法正常使用的&#xff0c;即…

Java Flight Record 详解

核心概念 Java Flight Record 提供一个低开销的数据收集框架&#xff0c;用于对 Java 应用程序和 HotSpot JVM 进行故障排除。Flight Recorder 记录源自应用程序、JVM和操作系统的事件 Flight Record&#xff0c;顾名思义&#xff0c;相当于飞机黑匣子里保存的飞行记录 事件 …

vue3+ts mitt的使用

安装mitt :npm i mitt -Smain.ts: import mitt from mittconst Mit mitt();declare module vue {export interface ComponentCustomProperties{$Bus:typeof Mit} } app.config.globalProperties.$BusMit在A组件中使用 <template><div><h1>我是A<…

Leetcode—160.相交链表【简单】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—160.相交链表 算法思想 两个链表的节点之和是相等的 如果两个链表相交&#xff0c;那么相交点之后的长度是相同的 我们需要做的事情是&#xff0c;让两个链表从同距离末尾同等距离的位置开始遍历。这个位置只能是较短…

【高可用架构】Haproxy 和 Keepalived 的区别

Haproxy 和 Keepalived 的区别 1.负载均衡器介绍2.Haproxy 和 Keepalived 的基本概念和特点2.1 Haproxy2.2 Keepalived 3.Haproxy 和 Keepalived 的区别3.1 功能上的区别3.2 架构上的区别3.3 配置上的区别 4.总结 1.负载均衡器介绍 负载均衡器是一种解决高并发和高可用的常用的…

【JavaSE】:数据类型

数据类型 一.总体概论二.java里与c的区别1.float2.char3.boolen 三.类型转换四.String类型 一.总体概论 在Java中数据类型主要分为两类&#xff1a;基本数据类型和引用数据类型。 不论是在16位系统还是32位系统&#xff0c;int都占用4个字节&#xff0c;long都占8个字节 。 整…

NAS非接入层协议学习(二)

在无线通信网络中 NAS (Non-Access Stratum)做为非接入层是演进分组系统(或5G核心网)中的一组协议。NAS用于在用户设备(UE)和移动管理实体(MME/AMF)之间传送非无线电信令&#xff0c;以实现NR/LTE/E-UTRAN接入。 NAS在协议栈中是控制面的最高层。 NAS协议分组中可以将其分为两…

3款免费的语音视频转文本AI神器

最近有很多粉丝让我出一期关于语音转文本的免费AI神器&#xff0c;毕竟这类工具在学习和工作中经常会用到&#xff0c;那今天就给大家安排。 我亲测了好几款软件之后&#xff0c;最终评选留下了三款 剪映hugging face飞书妙记 接下来一一给大家讲解 1.剪映 剪映其实是一款视…

因式分解的几何意义

本来准备和女儿一起玩一道几何题&#xff0c;想想还是算了&#xff0c;不如讲点更有趣的。 任何因式分解都是在堆积木&#xff0c;不信你看&#xff1a; 二项式定理&#xff0c;洋灰三角&#xff0c;都是面积&#xff0c;体积&#xff0c;超维体积的拼接&#xff0c;一个大超…

Python | CAP - 累积精度曲线分析案例

CAP通常被称为“累积精度曲线”&#xff0c;用于分类模型的性能评估。它有助于我们理解和总结分类模型的鲁棒性。为了直观地显示这一点&#xff0c;我们在图中绘制了三条不同的曲线&#xff1a; 一个随机的曲线&#xff08;random&#xff09;通过使用随机森林分类器获得的曲线…

leetcode_828_统计子串中的唯一字符

题意&#xff1a;所有子串中单个字符出现的次数和 问题转化&#xff1a;对于串中的每个字符&#xff0c;只包含其一次的所有子串的个数和 关于求只包含某位置字符一次的子串个数 class Solution { public:int uniqueLetterString(string s) {/* ...A...A...A...*/int n s.size…

【C++】类型转换 ② ( C++ 静态类型转换 static_cast | C 语言隐式转换弊端 | 代码示例 )

文章目录 一、静态类型转换 static_cast1、C 静态类型转换 static_cast2、C 语言隐式转换弊端3、代码示例 在之前写过一篇 C 类型转换的博客 【C 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 ) , 简单介绍了 C 类…

linklab phase1 更简单的方法

直接反汇编phase1.o&#xff0c;看eax中是0x21&#xff0c;0x21在数据域中&#xff0c;直接把从第21个字节的内容改为0000000000即可。

【python】--文件/文件夹读写及操作

目录 一、文件读写1、文件读写代码示例 二、文件/文件夹操作1、代码示例 一、文件读写 读写文件就是请求操作系统打开一个文件对象&#xff08;通常称为文件描述符&#xff09;&#xff0c;然后通过操作系统提供的接口从这个文件对象中读取数据&#xff08;读文件&#xff09;…

【如何修改输入法切换键】

操作 以win10为例&#xff0c;点开系统设置&#xff0c;选择时间和语言 选择语言&#xff0c;找到首选语言中的中文&#xff0c;点击选项 点击其中的微软输入法 选择按键 在按键中进行输入法切换按键的选择

Atcoder Beginner Contest 330——A~F题

A - Counting Passes Description Problem Statement N N N people labeled 1 , 2 , … , N 1,2,\dots,N 1,2,…,N took an exam, and person i i i scored A i A_i Ai​ points. Only those who scored at least L L L points pass this exam. Determine how many peopl…

【Linux】第二十一站:文件(一)

文章目录 一、共识原理二、C系列文件接口三、从C过渡到系统&#xff1a;文件系统调用四、访问文件的本质 一、共识原理 文件 内容 属性 文件分为打开的文件 和 没打开的文件 打开的文件&#xff1a;是谁打开的&#xff1f;是进程&#xff01;----所以研究打开的文件本质是研…

预制构件二维码如何生成?

PC预制构件张贴二维码标识牌&#xff0c;可实现预制构建基本信息、设计图纸、安装说明书信息展示微信扫一扫即可查看预制件信息&#xff0c;大大提高施工的精度和效率&#xff1b;同时也可以实现预制生成过程管理、运输过程管理、安装过程管理、后期运维管理实现预制件的过程质…