【数据结构c实现】顺序表实现

文章目录

  • 线性表
    • 线性表的顺序实现
      • 顺序表结构
      • 顺序表初始化
      • 增配空间Inc
      • 打印顺序表show_list
      • 线性表长度length
      • 尾部插入push_back
      • 头部插入push_front
      • 尾部删除pop_back
      • 头部删除pop_front
      • 按位置插入insert_pos
      • 按值查找find
      • 按位置删除delete_pos
      • 按值删除delete_val
      • 排序sort(冒泡;升序)
      • 逆置resver
      • 清除表clear
      • 销毁表destroy
      • 合并表merge

线性表

在数据元素的非空有限集中,(1)存在唯一的一个被称做“第一个”的数据元素;(2)存在唯一的一个被称做“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前驱;(4)除最后一个之外,集合中每个数据元素均只有一个后继

线性表的顺序实现

线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。

顺序表结构

#define SEQLIST_INIT_SIZE 8

typedef struct SeqList {
    ElemType *base; // 线性表首地址
    int capacity; // 开辟的内存空间
    int size; // 有效存储
} SeqList;

在这里插入图片描述

顺序表初始化

开辟出一段空间(给定空间大小)

void InitSeqList(SeqList *list) {
    list->base = (ElemType *) malloc(sizeof(ElemType) * SEQLIST_INIT_SIZE);//开辟空间
    assert(list->base != NULL);
    list->capacity = SEQLIST_INIT_SIZE;
    list->size = 0;
}

malloc动态内存分配函数,用于申请一块连续的指定大小的内存块区域以ElementType *类型返回分配的内存区域地址:格式:指针名=(指针类型*)malloc(sizeof(指针类型)*数据数量)

②如果表达式的结果为“假”,assert()会打印出断言失败的信息Assertion failed:...,并调用abort()函数终止程序的执行Process finished with exit code 3;如果表达式的结果为“真”,assert()就什么也不做,程序继续往后执行

增配空间Inc

1.重新开辟内存空间,并判断是否增配空间成功,失败则增配失败返回false

2.更新结点线性表首地址和开辟的内存空间

3.之后每次插入数据操作前,添加判断条件:分配给表内存是否足够。不够则进行增配空间,增配空间失败时,才是真正的内存不足

#define INC_SIZE 3

bool Inc(SeqList *list) {
    //对已有的空间进行分配,原来表开辟内存8,进行重新分配,即开辟8+3内存
    ElemType *newbase = (ElemType *) realloc(list->base, sizeof(ElemType) * (list->capacity + INC_SIZE));
    if (newbase == NULL) {
        printf("增配空间失败,内存不足\n");
        return false;
    }
    list->base = newbase;
    list->capacity += INC_SIZE;

    return true;
}

realloc函数指向在堆区重新开辟的内存块的起始地址:realloc(先前开辟的内存块的指针--也就是malloc之前申请的那块内存空间,即需要调整大小的内存空间,新开辟的那块内存空间的字节数),返回值为调整之后的内存的起始地址

打印顺序表show_list

void show_list(SeqList *list) {
    for (int i = 0; i < list->size; i++) {
        printf("%d", list->base[i]);
    }
    printf("\n");
}

线性表长度length

int length(SeqList *list) {
    return list->size;
}

尾部插入push_back

插入6 7 9后顺序表中数据顺序为:6 7 9

1.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

2.通过下标赋值,即插入数据

3.更新顺序表有效存储长度

void push_back(SeqList *list, ElemType x) {
    if (list->size >= list->capacity && !Inc(list)) {
        printf("顺序表空间已满,%d不能尾部插入数据\n", x);
        return;
    }
    list->base[list->size] = x;
    list->size++;
}

头部插入push_front

插入6 9 1后顺序表中数据顺序为:1 9 6

1.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

2.size-1即表中最后一个数据的下标,从最后一个数据开始依次向后移动

3.赋值到下标为0的地址,即插入数据

4.更新顺序表有效存储长度

void push_front(SeqList *list, ElemType x) {
    if (list->size >= list->capacity && !Inc(list)) {
        printf("顺序表空间已满,%d不能头部插入数据\n", x);
        return;
    }
    for (int i = list->size; i > 0; i--) {
        list->base[i] = list->base[i - 1];
    }
    list->base[0] = x;
    list->size++;
}

尾部删除pop_back

有顺序表1 6 9进行尾部删除后:1 6

1.判断size是否为0,即表是否为空,空表不能删除数据

2.有效长度减1

void pop_back(SeqList *list) {
    if (list->size == 0) {
        printf("顺序表空间已空,不能尾部删除数据\n");
        return;
    }
    list->size--;
}

头部删除pop_front

有顺序表5 6 0进行头部删除后:6 0

1.判断size是否为0,即表是否为空,空表不能删除数据

2.从第二个数据开始,依次往前移动

3.有效长度减1

void pop_front(SeqList *list) {
    if (list->size == 0) {
        printf("顺序表空间已空,不能头部删除数据\n");
        return;
    }
    for (int i = 0; i < list->size - 1; i++) {
        list->base[i] = list->base[i + 1];
    }
    list->size--;
}

按位置插入insert_pos

在顺序表5 3 0下标为2的位置插入数据7为:5 3 7 0

1.判断pos是否正确并小于有效存储长度,即判断插入位置是否合法,位置非法不能插入数据

2.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

3.从最后一个数据开始依次向后移动,直到要插入数据的位置移动结束

4.通过下标赋值,即插入数据

5.更新顺序表有效存储长度

void insert_pos(SeqList *list, int pos, ElemType x) {
    if (pos < 0 || pos > list->size) {
        printf("插入数据的位置非法,不能插入数据\n");
    }
    if (list->size >= list->capacity && !Inc(list)) {
        printf("顺序表空间已满,%d不能按位置插入数据\n", x);
        return;
    }
    for (int i = list->size; i > pos; i--) {
        list->base[i] = list->base[i - 1];
    }
    list->base[pos] = x;
    list->size++;
}

特殊情况:当要插入数据的位置==有效存储长度时,即尾部插入时,不影响效率[特别注意]

按值查找find

(第一个符合条件的)

1.从顺序表第一个数据开始向后遍历

2.每次遍历判断该数据是否是要查找的数据,查找成功返回当前下标

3.遍历结束,即没查到数据,返回-1

int find(SeqList *list, ElemType key) {
    for (int i = 0; i < list->size; i++) {
        if (list->base[i] == key)
            return i;
    }
    return -1;
}

按位置删除delete_pos

顺序表5 3 0删除位置为1的数据后:5 0

1.判断pos是否正确并小于有效存储长度,即判断删除位置是否合法,位置非法不能删除数据

2.从要删除的位置开始,依次将后一个数据前移

3.更新顺序表有效存储长度

void delete_pos(SeqList *list, int pos) {
    if (pos < 0 || pos >= list->size)
        printf("删除数据的位置非法,不能删除数据\n");
    for (int i = pos; i < list->size - 1; i++) {
        list->base[i] = list->base[i + 1];
    }
    list->size--;
}

按值删除delete_val

顺序表5 3 0删除值为0的数据后:5 3

1.判断要删除的数据是否存在,即按值查找,存在得到查找到的数据下标,不存在得到-1

2.判断返回值是否是-1,是则数据不存在无法删除,否则按位置删除

void delete_val(SeqList *list, ElemType key) {
    int pos = find(list, key);
    if (pos == -1) {
        printf("要删除的数据不存在\n");
        return;
    }
    delete_pos(list, pos);
}

排序sort(冒泡;升序)

顺序表5 3 0 1 9 4排序后:0 1 3 4 5 9

1.两层遍历,依次比较两个数据,前面数据大于后面数据则交换

void sort(SeqList *list) {
    for (int i = 0; i < list->size; i++) {
        for (int j = 0; j < list->size - i - 1; j++) {
            if (list->base[j] > list->base[j + 1]) {
                ElemType tmp = list->base[j];
                list->base[j] = list->base[j + 1];
                list->base[j + 1] = tmp;
            }
        }
    }
}

逆置resver

顺序表5 3 0 1 9 4逆置后:4 9 1 0 3 5

1.判断顺序表长度是否可进行逆置操作操作,长度为1或0时不需要

2.设置两个整型指针low和high,分别指向第一个数据和最后一个数据,low指针后移,high指针前移,每次将两个指针指向的数据对换,直到low指针大于或等于high指针为止

void resver(SeqList *list) {
    if (list->size == 0 || list->size == 1)
        return;
    int low = 0;
    int high = list->size - 1;
    ElemType tmp;
    while (low < high) {
        tmp = list->base[low];
        list->base[low] = list->base[high];
        list->base[high] = tmp;
        low++;
        high--;
    }
}

清除表clear

void clear(SeqList *list) {
    list->size = 0;
}

销毁表destroy

void destroy(SeqList *list) {
    free(list->base);
    list->base = NULL;
    list->capacity = 0;
    list->size = 0;
}

free函数必须和malloc函数同时使用

free只能释放由malloc动态分配在堆内存的内存,直接在主函数定义结构体变量是分配在栈内存里的内存,所以释放不了

合并表merge

表A1 2 5 6,表B3 4 7 9,合并后:1 2 3 4 5 6 9

1.设置iaibic三个整型指针,分别用来遍历表A、B、合并表,开辟存放合并表的内存空间,并判断是否开辟成功

2.同时遍历表A和表B,依次判断指针指向的A、B表的数据大小,将较小的数据放入合并表,每存入一个数据,合并表和被存入的数据所在表的整型指针都向后移一次,直到A、B有一个表遍历完

3.如果其中一个表遍历结束,另一个表还有遍历完的数据,则直接将剩余数据依次存入合并表

4.更新合并表有效存储长度

void merge(SeqList *lt, SeqList *la, SeqList *lb) {
    lt->capacity = la->size + la->size;
    lt->base = (ElemType *) malloc(sizeof(ElemType)*lt->capacity);
    assert(lt->base != NULL);
    int ia = 0;
    int ib = 0;
    int ic = 0;

    while(ia<la->size && ib<lb->size)
    {
        if(la->base[ia] < lb->base[ib])
            lt->base[ic++] = la->base[ia++];
        else
            lt->base[ic++] = lb->base[ib++];
    }
    while(ia < la->size)
    {
        lt->base[ic++] = la->base[ia++];
    }
    while(ib < lb->size)
    {
        lt->base[ic++] = lb->base[ib++];
    }
    lt->size = la->size + lb->size;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式--行为型--观察者模式】

设计模式--行为型--观察者模式 观察者模式定义结构案例优缺点使用场景JDK中提供的实现例&#xff1a;警察抓小偷 观察者模式 定义 又被成为发布订阅模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生…

6.23删除二叉搜索树中的节点(LC450-M)

算法&#xff1a; 一共有五种可能的情况&#xff1a; 第一种情况&#xff1a;没找到删除的节点&#xff0c;遍历到空节点直接返回了找到删除的节点 第二种情况&#xff1a;左右孩子都为空&#xff08;叶子节点&#xff09;&#xff0c;直接删除节点&#xff0c; 返回NULL为根…

学习笔记10——Mysql的DDL语句

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/197161.html 数据库创建&#xff1a; CREATE DATABASE books&#xff1b; CREATE DATABASE IF NOT EXISTS books;更改字符集 ALTER DATABASE books CHARACTER SET gbk;库的删…

《数据结构、算法与应用C++语言描述》- 构建哈夫曼树

哈夫曼树 完整可编译运行代码见&#xff1a;Github::Data-Structures-Algorithms-and-Applications/_29huffmanTree 定长编码与可变长编码 定长编码 每个字符都用固定长度的编码来表示。 例如假设一个文本是由字符 a、u、x 和 z 组成的字符串&#xff0c;每个字符用2位二进…

ShardingSphereJDBC简单入门

ShardingSphere 介绍ShardingSphere-JDBCSharding-Sphere-ProxyShardingSphere-Sidecar混合架构运行模式DistSQL可拔插架构ShardingSphere的发展路线 主从复制ShardingSphere-JDBC功能SQL解析SQL支持程度SQL稳定支持SQL实验性支持 MySQL不支持SQL清单分页 数据分片垂直分片水平…

不再花冤枉钱!教你怎么选知识付费平台

在当今的知识付费市场中&#xff0c;用户面临的选择越来越多&#xff0c;如何从众多知识付费平台中正确选择属于自己的平台呢&#xff1f;下面&#xff0c;我们将为您介绍明理信息科技知识付费平台相比同行的优势&#xff0c;帮助您做出明智的选择。 一、创新的技术架构&#…

docker部署go gin框架 Windows环境

目录 文章目的是什么 环境介绍 Windows 环境下 docker 部署 go gin 详细步骤 运行容器时因为挂载文件可能会出现的问题 直接部署gin&#xff08;跳过运行容器时因为挂载文件可能会出现的问题&#xff09; 文章目的是什么 假设我们学习了 go 语言&#xff0c;在 Windows(本…

C语言 简单使用qsort 比较结构体字符串大小

1.先简单调用C语言封装好的冒泡排序 #include<stdio.h> #include<stdlib.h> #include<string.h> //qsort C语言封装好的冒泡排序 可比较任何类型 struct stu{char name[20];int age; }; //用户自己写的函数。函数名字也作为函数指针使用。是qsort函数的第四…

代码随想录第三十三天(一刷C语言)|斐波那契数爬楼梯使用最小花费爬楼梯

创作目的&#xff1a;为了方便自己后续复习重点&#xff0c;以及养成写博客的习惯。 动态规划步骤&#xff1a; 确定dp数组以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 一、斐波那契数 思路&#xff1a;参考carl文档 1、dp[i]的定义为&#xff…

PDI/Kettle-9.2.0.0-R(对应jdk1.8)源码编译问题记录及源码结构简介

目录 &#x1f4da;第一章 前言&#x1f4d7;背景&#x1f4d7;目的&#x1f4d7;总体方向 &#x1f4da;第二章 代码结构初识基本结构&#x1f4d7;代码模块详情 ⁉️问题记录❓问题一&#xff1a;代码分支哪些是发布版本❗答&#xff1a;后缀-R的版本 ❓问题二&#xff1a;50…

猫粮哪个牌子质量好性价比高?盘点十款主食冻干猫粮品牌排行榜!

在过去的100多年里&#xff0c;猫咪主食市场一直被膨化猫粮主导。然而&#xff0c;随着猫咪频频出现猝死、失明、发育不良以及营养不良等问题&#xff0c;猫主人们开始质疑膨化粮是否最适合猫咪。于是&#xff0c;从上世纪90年代开始&#xff0c;出现了生骨肉喂养。生骨肉确实是…

[算法总结] 十大排序算法

[算法总结] 十大排序算法 简介&#xff1a; 本文首发于我的个人博客&#xff1a;尾尾部落排序算法是最经典的算法知识。因为其实现代码短&#xff0c;应该广&#xff0c;在面试中经常会问到排序算法及其相关的问题。一般在面试中最常考的是快速排序和归并排序等基本的排序算法…

代码随想录算法训练营 | day48 动态规划 198.打家劫舍,213.打家劫舍Ⅱ,337.打家劫舍Ⅲ

刷题 198.打家劫舍 题目链接 | 文章讲解 | 视频讲解 题目&#xff1a;你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被…

c YUV 转 JPEG(准备霍夫曼编码)

先取yuv 文件中一个168的块&#xff0c;跑通全流程 理解与思路&#xff1a; 1.块分割 YUV 文件分为&#xff1a;YUV444 YUV 422 YUV420。444:就是&#xff1a;12个char 有4个Y&#xff0c;4个U&#xff0c;4个 U&#xff0c;422&#xff1a;8个char 中有4个Y &#x…

Oracle MongoDB

听课的时候第一次碰到&#xff0c;可以了解一下吧&#xff0c;就直接开了墨者学院的靶场 #oracle数据库 Oracle数据库注入全方位利用 - 先知社区 这篇写的真的很好 1.判断注入点 当时找了半天没找到 看样子是找到了&#xff0c;测试一下看看 id1 and 11 时没有报错 2.判断字段…

开发人员必须掌握的几个高级命令

xargs命令 在平时的使用中,我认为 xargs 这个命令还是较为重要和方便的。我们可以通过使用这个命令,将命令输出的结果作为参数传递给另一个命令。 比如说我们想找出某个路径下以 .conf 结尾的文件,并将这些文件进行分类,那么普通的做法就是先将以 .conf 结尾的文件先找出…

linux(centos7)mysql8.0主从集群搭建(两台机器)

docker安装:&#xff08;转载&#xff09;centos7安装Docker详细步骤&#xff08;无坑版教程&#xff09;-CSDN博客 环境信息 主数据库服务器&#xff1a;192.168.1.10 从数据库服务器&#xff1a;192.168.1.11 1. mysql8.0镜像下载 docker pull mysql:8.0.23 2.创建docke…

SaaS 电商设计 (五) 私有化部署-实现 binlog 中间件适配

一、 背景 具体的中间件私有化背景在上文 SaaS 电商设计 (二) 私有化部署-缓存中间件适配 已有做相关介绍.这里具体讨论的场景是通过解析mysql binlog 来实现mysql到其他数据源的同步.具体比如:在电商的解决方案业务流中经常有 ES 的使用场景,用以解决一些复杂的查询和搜索商品…

17--异常处理

1、异常概述 1.1 什么是异常 异常&#xff1a;指的是程序在执行过程中&#xff0c;出现的非正常情况&#xff0c;如果不处理最终会导致JVM的非正常停止。 异常指的并不是语法错误和逻辑错误。语法错了&#xff0c;编译不通过&#xff0c;不会产生字节码文件&#xff0c;根本运…

01.前言

前言 1.什么是前端开发 前端开发是创建 Web 页面或 app 等前端界面呈现给用户的过程核心技术&#xff1a;HTML&#xff0c;CSS&#xff0c;JavaScript 以及衍生出的各种技术&#xff0c;框架等 2.前端开发应用场景 3.前端职业路线 4.什么是CS架构与BS架构 介绍 应用软件&a…