数据结构——线性表和顺序表

1、线性表的基本概念

1.1 定义

        线性结构是简单且常用的数据结构,而线性表则是一种典型的线性结构

        存储数据,最简单,最有效的方法是吧它们存储在一个线性表中

        一个线性表是n个元素的有限序列。每个元素在不同的情况下有不同的含义,可以是整数,也可以是字符

        线性表:是具有相同数据类型的n个数据元素的有限序列

1.2 特点:围绕一对一关系进行描述

        存在唯一的第一个元素

        存在唯一的最后一个元素

        除第一个元素外,每一个元素只有一个直接前驱

        除最后一个元素外,每一个元素均只有一个直接后继

1.3 逻辑结构:线性结构 

1.4 线性表的存储结构

        顺序存储结构:顺序表

        链式存储结构:链表

1.5 操作

        表:创建、销毁

        数据: 增删改查

2、顺序表

2.1 定义

        就是把线性表中的所有元素按照其逻辑顺序依次存储到指定位置开始的一块连续的存储区域

        线性表中的第1个元素的存储位置就是指定的存储位置,第i个元素的存储位置紧接第i-1个元素的存储位置的后面

2.2 特点

        顺序表的元素是按顺序进行存储的,第i项就存在第i个位置

        对顺序表中的所有元素,既可以顺序访问,也可以随机访问,比较擅长随机访问和遍历

        不擅长插入、删除操作,需要移动大量元素

2.3 操作

        表:创建、销毁

        数据: 增删改查

2.4 顺序表的实现方式:数组、指针 

2.4.1 顺序表的数组的实现方式

顺序表和数组进行对比

        1、数组是一种特殊的顺序表

        2、顺序表是通过数组来实现的,顺序表的元素存储在一块连续的存储空间中

        3、数组的长度是不可变的,顺序表的长度是可以改变的

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <memory.h>  //需要使用memset时引用
//创建顺序表结构体类型
#define MAX_SIZE 100  //宏定义,为了维护简单
typedef int elementType;  //重命名,为了维护简单
typedef struct Order_List {
    elementType data[MAX_SIZE];  //数组:存放顺序表元素
    int lenth;  //顺序表的元素总个数
}OrderList;

void print_menu();
OrderList* create_list();
void append_List(OrderList* List, elementType val);
void print_List(OrderList* List);
void insert_List(OrderList* List, int index, elementType val);
void delete_List(OrderList* List, int index);
void edit_List(OrderList* List, int index, elementType val);
void destory_List(OrderList* List);

int main() {
    print_menu();
    int order = 0;  //存储用户输入的操作指令
    //创建顺序表变量
    //OrderList list;  //结构体变量,静态分配
    OrderList* List = NULL;  //结构体指针,动态申请,手动释放
    elementType val = 0;
    int index = 0;
    while (1) {
        printf("请输入操作指令:");
        scanf("%d", &order);
        switch (order) {
            case 1:  //创建顺序表
                //创建空表
                List = create_list();
                break;
            case 2:  //打印顺序表
                print_List(List);
                break;
            case 3:  //追加一个节点,尾部插入
                printf("请输入要追加的元素:");
                scanf(" %d", &val);
                append_List(List, val);
                break;
            case 4:  //插入一个节点,随机插入,从0开始
                printf("请输入要插入的位置:");
                scanf(" %d", &index);
                printf("请输入要插入的元素:");
                scanf(" %d", &val);
                insert_List(List, index, val);
                break;
            case 5:  //删除一个节点,从1开始
                printf("请输入要删除第几个元素:");
                scanf(" %d", &index);
                delete_List(List, index);
                break;
            case 6:  //修改顺序表元素,从1开始
                printf("请输入要修改的元素位置:");
                scanf(" %d", &index);
                printf("请输入修改后的新值:");
                scanf(" %d", &val);
                edit_List(List, index, val);
                break;
            case 7:  //销毁顺序表

                //List存放的是表的地址,需要销毁List的地址,才能销毁顺序表
                destory_List(&List);
                break;
            case 8:  //退出
                break;
            default:
                printf("输入错误,请重新输入!");
        }
        if (order == 8) {
            break;
        }
    }
    return 0;
}

//打印菜单
void print_menu() {
    system("cls");  //系统函数,用于屏幕清空
    printf("操作指令:\n");
    printf("1、创建顺序表\n");
    printf("2、打印顺序表\n");
    printf("3、追加一个节点\n");
    printf("4、插入一个节点\n");
    printf("5、删除一个节点\n");
    printf("6、修改顺序表元素\n");
    printf("7、销毁顺序表\n");
    printf("8、退出\n");
}

//创建空表
OrderList* create_list() {
    //申请内存
    //malloc分配的内存空间不确定,一般使用memset初始化
    OrderList* List = (OrderList*)malloc(sizeof(OrderList));  
    //申请失败
    if (List == NULL) {
        printf("内存申请失败,创建失败!\n");
        return NULL;
    }
    //申请成功
    //需要导入memory.h或string.h
    memset(List, 0, sizeof(OrderList));  //功能:将指定内存设置为指定内容,一般用来进行数组清零
    List->lenth = 0;
    printf("初始化成功!\n");
    return List;
}

//追加一个节点,末尾增加
void append_List(OrderList* List, elementType val) {
    //判断是否初始化
    if (List == NULL) {  //!List
        printf("请先建表\n");
        return;
    }
    //判断表是否已满
    if (List->lenth >= MAX_SIZE) {
        printf("表已满,无法追加!\n");
        return;
    }
    //正常追加
    List->data[List->lenth] = val;
    List->lenth++;
    printf("追加成功!\n");
}

//打印顺序表
void print_List(OrderList* List) {
    //判断是否初始化
    if (List == NULL) {  //!List
        printf("请先建表\n");
        return;
    }
    
    if (List->lenth == 0) {
        printf("空表,无法打印!\n");
        return;
    }
    //正常打印
    for (int i = 0;i < List->lenth;i++) {
        printf("%d ", List->data[i]);
    }
    printf("\n");
}

//插入一个节点,随机插入
void insert_List(OrderList* List, int index, elementType val) {
    //判断是否初始化
    if (List == NULL) {  //!List
        printf("请先建表\n");
        return;
    }
    //判断表是否已满
    if (List->lenth == 0) {
        printf("空表,无法打印!\n");
        return;
    }
    //正常插入,倒序遍历,位置后移
    for (int i = List->lenth - 1;i >= index;i--) {
        List->data[i + 1] = List->data[i];
    }
    List->data[index] = val;
    List->lenth++;
    printf("插入成功!\n");
}

//删除
void delete_List(OrderList* List, int index) {
    //判断是否初始化
    if (List == NULL) {  //!List
        printf("请先建表\n");
        return;
    }
    //判断索引是否合法
    int ind = index - 1;  //要删除的元素的索引
    if (ind<0 || ind>List->lenth - 1) {
        printf("请输入合适的位置!\n");
        return;
    }
    //执行删除,元素前移
    for (int i = ind;i < List->lenth;i++) {
        List->data[i] = List->data[i + 1];
    }
    List->lenth--;
    printf("删除成功!\n");
}

//修改
void edit_List(OrderList* List, int index, elementType val) {
    //判断是否初始化
    if (List == NULL) {  //!List
        printf("请先建表\n");
        return;
    }
    //判断索引是否合法
    int ind = index - 1;  //要删除的元素的索引
    if (ind<0 || ind>List->lenth - 1) {
        printf("您要修改的元素不存在!\n");
        return;
    }
    //执行修改
    List->data[ind] = val;
    printf("修改成功!\n");
}

//销毁  注意:形参是二级指针
void destory_List(OrderList** List) {
    free(*List);  //释放内存空间
    *List = NULL;  //销毁后要置空
    printf("销毁成功!\n");
}

2.4.2 顺序表的指针的实现方式

2.4.2.1 02.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <memory.h> 
#define MAX_SIZE 100
typedef int ElementT;
//定义结构体类型
typedef struct OrderListPtr {
    ElementT* datap;  //元素类型指针,用于申请内存后,存放数组元素
    int length;  //存放数组元素的总个数
}ODP;
void print_menu();
void create_List(ODP* list);
void append_List(ODP* list, ElementT value);
void print_List(ODP list);
void insert_List(ODP* list, int index, ElementT value);
void delete_List(ODP* list, int index);
void delete_List(ODP* list, int index);
void edit_List(ODP* list, int index, ElementT value);
void destroy_List(ODP* list);

2.4.2.1 02.c

#include "02.h"
//顺序表的指针的实现方式

//如果要改datap或length的值需要传地址,不需要则传值

void fn2() {
    while (1) {
        print_menu();
        int order = 0;  //存储用户输入的操作指令
        ODP list = { NULL,0 };  //定义结构体变量
        ElementT value = 0;
        int index = 0;
        while (1) {
            printf("请输入操作指令:");
            scanf("%d", &order);
            switch (order) {
            case 1:  //创建顺序表
                //创建空表
                create_List(&list);
                break;
            case 2:  //打印顺序表
                print_List(list);
                break;
            case 3:  //追加一个节点,尾部插入
                printf("请输入要追加的元素:");
                scanf(" %d", &value);
                append_List(&list, value);
                break;
            case 4:  //插入一个节点,随机插入,从0开始
                printf("请输入要插入的元素的位置:");
                scanf(" %d", &index);
                printf("请输入要插入的元素:");
                scanf(" %d", &value);
                insert_List(&list, index, value);
                break;
            case 5:  //删除一个节点,从1开始
                printf("请输入要删除的元素的位置:");
                scanf(" %d", &index);
                delete_List(&list, index);
                break;
            case 6:  //修改顺序表元素,从1开始
                printf("请输入要修改的元素的位置:");
                scanf(" %d", &index);
                printf("请输入要修改的元素:");
                scanf(" %d", &value);
                edit_List(&list, index, value);
                break;
            case 7:  //销毁顺序表
                destroy_List(&list);
                break;
            case 8:  //退出
                break;
            default:
                printf("输入错误,请重新输入!");
            }
            if (order == 8) {
                break;
            }
        }
        return 0;
    }
}
//打印菜单
void print_menu() {
    system("cls");  //系统函数,用于屏幕清空
    printf("操作指令:\n");
    printf("1、创建顺序表\n");
    printf("2、打印顺序表\n");
    printf("3、追加一个节点\n");
    printf("4、插入一个节点\n");
    printf("5、删除一个节点\n");
    printf("6、修改顺序表元素\n");
    printf("7、销毁顺序表\n");
    printf("8、退出\n");
}
//创建顺序表
void create_List(ODP* list) {
    //申请内存空间
    list->datap = (ElementT*)malloc(sizeof(ElementT*) * MAX_SIZE);
    if (!list->datap) {
        printf("内存申请失败!\n");
        return;
    }
    //清0
    memset(list->datap, 0, sizeof(ElementT*) * MAX_SIZE);
    list->length = 0;
    printf("初始化成功!\n");
}

//追加一个节点,尾部插入
void append_List(ODP* list, ElementT value) {
    //判断是否建过表
    if (!list->datap) {
        printf("请先建表!\n");
        return;
    }
    //判断表是否满
    if (list->length >= MAX_SIZE) {
        printf("表已满,无法追加!\n");
        return;
    }
    //正常追加
    *(list->datap + list->length) = value;  //list->datap首元素的地址
    另一种方法
    //list->datap[list->length] = value;
    list->length++;
    printf("追加成功!\n");
}

//打印顺序表
void print_List(ODP list) {
    if (!list.datap) {
        printf("请先建表!\n");
        return;
    }
    if (list.length == 0) {
        printf("空表,无法打印!\n");
        return;
    }
    for (int i = 0;i < list.length;i++) {
        printf("%d ", list.datap[i]);  //当成数组
        另一种方法
        //printf("%d ", *(list.datap + i));  //当成指针
    }
    printf("\n");
}

//插入一个节点,随机插入,从0开始
void insert_List(ODP* list, int index, ElementT value) {
    //判断是否建过表
    if (!list->datap) {
        printf("请先建表!\n");
        return;
    }
    //判断表是否满
    if (list->length >= MAX_SIZE) {
        printf("表已满,无法插入!\n");
        return;
    }
    //正常插入
    //从index位置,倒叙遍历,位置后移
    for (int i = list->length - 1;i >= index;i--) {
        list->datap[i + 1] = list->datap[i];
    }
    //判断插入的位置是否合法
    if (index<0 || index>list->length - 1) {
        printf("插入位置不合法!\n");
        return;
    }
    list->datap[index] = value;
    另一种方法
    //*(list->datap + list->length) = value;
    list->length++;
    printf("插入成功!\n");
}

//删除一个节点,从1开始
void delete_List(ODP* list, int index) {
    //判断是否建过表
    if (!list->datap) {
        printf("请先建表!\n");
        return;
    }
    if (list->length == 0) {
        printf("空表,无法删除!\n");
        return;
    }
    //判断要删除的元素的位置是否合法
    int ind = index - 1;
    if (ind<0 || ind>list->length - 1) {
        printf("您要删除的元素不存在!\n");
        return;
    }
    //正常删除,从index开始,所有元素前移
    for (int i = ind;i < list->length;i++) {
        list->datap[i] = list->datap[i + 1];
    }
    list->length--;
    printf("删除成功!\n");
}

//修改顺序表元素,从1开始
void edit_List(ODP* list, int index, ElementT value) {
    //判断是否建过表
    if (!list->datap) {
        printf("请先建表!\n");
        return;
    }
    if (list->length == 0) {
        printf("空表,无法修改!\n");
        return;
    }
    //判断要修改的元素的位置是否合法
    int ind = index - 1;
    if (ind<0 || ind>list->length - 1) {
        printf("您要修改的元素不存在!\n");
        return;
    }
    //正常修改
    list->datap[ind] = value;
    另一种方法
    //*(list->datap + ind) = value;
    printf("修改成功!\n");
}

//销毁顺序表
void destroy_List(ODP* list) {
    //判断是否建过表
    if (!list->datap) {
        printf("请先建表!\n");
        return;
    }
    free(list->datap);  //释放内存
    list->datap = NULL;
    list->length = 0;
    printf("销毁成功!\n");
}

2.4.2.1 02main.c 

#include "02.h"
int main() {
    fn2();
    return 0;
}

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

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

相关文章

Linux系统离线部署MySQL详细教程(带每步骤图文教程)

1、登录官网下载对应的安装包 MySQL :: Developer Zone 2、将压缩包上传到服务器上&#xff0c;这里直接上传到/usr/local路径上 使用sftp工具上传到/usr/local目录上 3、解压压缩包 tar -xf mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz 4、将mysql-8.0.39-linux-glibc2.17…

leetcode刷题记录(六十一)——73. 矩阵置零

&#xff08;一&#xff09;问题描述 73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09;73. 矩阵置零 - 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 [http://baike.baidu.com/item/%E5%8E%9F%E5%9…

人机交互(包含推荐软件)

视觉交互、语音交互、笔式交互、触觉交互、虚拟环境交互。 主要的研究方面包括&#xff1a;人机交互界面表示模型与设计方法、可用性工程、可用性评估模型和方法、多模态智能交互技术、智能交互认知技术、语音识别交互、web界面交互设计、移动界面交互设计。 交互设计流程&am…

解锁未来情感科技:AI 机器人 Ropet 搭载的前沿智能黑科技

2025年的国际消费电子产品展览会&#xff08;CES&#xff09;上&#xff0c;一只可爱的“毛绒玩具”成了全场焦点。 当然&#xff0c;这并不是一个单纯的玩偶&#xff0c;而是和《超能陆战队》的大白一样温暖的陪伴机器人。 相信有很多人和小编一样&#xff0c;当年看完《超能…

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载,Scroll滚动到顶部

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载 效果展示 使用方法 import LoadingText from "../components/LoadingText" import PageToRefresh from "../components/PageToRefresh" import FooterBar from "../components/…

Flink(八):DataStream API (五) Join

1. Window Join Window join 作用在两个流中有相同 key 且处于相同窗口的元素上。这些窗口可以通过 window assigner 定义&#xff0c;并且两个流中的元素都会被用于计算窗口的结果。两个流中的元素在组合之后&#xff0c;会被传递给用户定义的 JoinFunction 或 FlatJoinFunct…

Flink CDC 在阿里云实时计算Flink版的云上实践

摘要&#xff1a;本文整理自阿里云高级开发工程师&#xff0c;Apache Flink Committer 阮航老师在 Flink Forward Asia 2024 生产实践&#xff08;三&#xff09;专场中的分享&#xff0c;主要分为以下四个方面&#xff1a; Flink CDC & 实时计算 Flink CDC YAML 核心功能…

如何使用wireshark 解密TLS-SSL报文

目录 前言 原理 操作 前言 现在网站都是https 或者 很多站点都支持 http2。这些站点为了保证数据的安全都通过TLS/SSL 加密过&#xff0c;用wireshark 并不能很好的去解析报文&#xff0c;我们就需要用wireshark去解密这些报文。我主要讲解下mac 在 chrome 怎么配置的&…

【大模型系列篇】数字人音唇同步模型——腾讯开源MuseTalk

之前有一期我们体验了阿里开源的半身数字人项目EchoMimicV2&#xff0c;感兴趣的小伙伴可跳转至《AI半身数字人开箱体验——开源项目EchoMimicV2》&#xff0c;今天带大家来体验腾讯开源的数字人音唇同步模型MuseTalk。 MuseTalk 是一个实时高品质音频驱动的唇形同步模型&#…

C++基础入门(二)

目录 前言 一、重载 1.函数重载 2.运算符重载 二、构造函数 1.什么是构造函数 2.带参数的构造函数 3.使用初始化列表 4.this关键字 5.new关键字 三、析构函数 1.什么是析构函数 四、静态成员变量 1.静态成员的定义 2.静态成员变量的作用 五、继承 1.继承基本概…

基础vue3前端登陆注册界面以及主页面设计

1.下载依赖 "element-plus/icons": "^0.0.11", "element-plus/icons-vue": "^2.3.1", "fortawesome/fontawesome-svg-core": "^6.7.2", "fortawesome/free-solid-svg-icons": "^6.7.2", &quo…

Mybatis-Plus:乐观锁与悲观锁

文章目录 一、场景二、乐观锁与悲观锁三、模拟修改冲突3.1 数据库中增加商品表3.2 添加数据3.3 添加实体3.4 添加mapper3.5 测试 四、乐观锁实现流程4.1 Mybatis-Plus实现乐观锁 一、场景 一件商品&#xff0c;成本价是80元&#xff0c;售价是100元。老板先是通知小李&#xf…

卷积神经网络——食物分类

整体框架&#xff1a; 导入库 导入了各种必需的Python库&#xff0c;用于数据处理、图像读取、模型构建和训练。 设置随机种子 seed_everything: 用于设置所有随机数生成器的种子&#xff0c;确保每次运行时的结果都是相同的。 图像预处理&#xff08;transform&#xff09; 对…

Jmeter配置服务代理器 Proxy(二)

1.创建脚本记录器 2.配置&#xff1a;Jmeter代理、端口、记录目标等 3.配置谷歌浏览器代理 浏览器配置代理的详细教程可参考&#xff1a;使用whistle代理-CSDN博客 4.启动Jmeter记录器 点击ok后弹出这个界面&#xff0c;生成了证书&#xff1a; 5.给浏览器安装Jmeter代理的证书…

灰色预测and BP神经网络 (详细上手使用)

灰色预测模型 基础知识&#xff1a; 白色系统&#xff1a;系统的信息是完全明确的。 灰色系统&#xff1a;系统的部分信息已知&#xff0c;部分信息未知。 黑色系统&#xff1a;系统的内部信息是未知的。 灰色预测是对既含有已知信息又含有不确定信息的系统进行预则&#xf…

mac 安装 node

brew versions node // 安装 node brew versions node14 // 安装指定版本 卸载node: sudo npm uninstall npm -g sudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.* sudo rm -rf /usr/local/include/node /Users/$USER/.npm su…

【Unity】unity3D 调用LoadSceneAsync 场景切换后比较暗 部门材质丢失

解决方法&#xff1a;两个场景使用同样灯光 现象 直接进入第二个场景是可以正常显示 调用LoadSceneAsync来切换后&#xff0c;第二个场景出现比较暗的情况 解决方法&#xff1a;两个场景使用同样灯光&#xff0c;在loading 的场景中加入灯光。 Light—Directional Light 如果…

红日-VulnStack靶场一

http://vulnstack.qiyuanxuetang.net/vuln/ 一、环境部署 win7(被攻击机/关火墙) web服务器 1张外网网卡(桥接192.168.1.105)&#xff0c;一张内网网卡192.168.52.143/255.255.255.0/192.168.52.2 DNS 192.168.52.138 winser2008 域控服务器 1张…

实现linux硬盘smart检测

一、下载交叉编译libatasmart库 下载链接&#xff1a;https://www.linuxfromscratch.org/blfs/view/svn/general/libatasmart.html libatasmart库编译依赖libudev库&#xff0c;交叉编译器前先准备依赖的libudev: 设置libudev的环境变量&#xff0c;并通过configure编译文件生…

蓝桥杯算法|基础笔记(1)

**时间复杂度** 一、概念理解 时间复杂度是用来衡量算法运行时间随输入规模增长而增长的量级。它主要关注的是当输入规模趋向于无穷大时&#xff0c;算法执行基本操作的次数的增长趋势&#xff0c;而不是精确的运行时间。 二、分析代码中的基本操作 确定关键操作 在一段代码…