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

news2025/1/16 10:44:08

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.coloradmin.cn/o/2277497.html

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

相关文章

EasyLine(v2.0)自制光谱、曲线处理软件

前言&#xff1a;因为这次更新对软件的整体变动较大&#xff0c;所以就没有取版本v1.1&#xff0c;而是直接使用v2.0版本。然后上一版的讲解也不是很清楚&#xff0c;这次也做重点讲解一下。 自制光谱、曲线处理软件-EasyLine 软件的安装软件的使用总体介绍文件格式处理的使用 …

赛灵思(Xilinx)公司Artix-7系列FPGA

苦难从不值得歌颂&#xff0c;在苦难中萃取的坚韧才值得珍视&#xff1b; 痛苦同样不必美化&#xff0c;从痛苦中开掘出希望才是壮举。 没有人是绝对意义的主角&#xff0c; 但每个人又都是自己生活剧本里的英雄。滑雪&#xff0c;是姿态优雅的“贴地飞行”&#xff0c;也有着成…

晨辉面试抽签和评分管理系统之八:随机编排考生的面试批次(以教师资格考试面试为例)

晨辉面试抽签和评分管理系统&#xff08;下载地址:www.chenhuisoft.cn&#xff09;是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…

LeetCode热题100(三十四) —— 23.合并K个升序链表

LeetCode热题100&#xff08;三十四&#xff09; —— 23.合并K个升序链表 题目描述代码实现思路一&#xff1a;选择排序(199ms)思路二&#xff1a;归并排序(2ms) 思路解析 你好&#xff0c;我是杨十一&#xff0c;一名热爱健身的程序员在Coding的征程中&#xff0c;不断探索与…

深入理解 ECMAScript 2024 新特性:字符串 isWellFormed 方法

ECMAScript 2024 引入了一个新的字符串实例方法&#xff1a;String.prototype.isWellFormed。这一新增功能是为了帮助开发者更容易地验证字符串是否为有效的 Unicode 文本。本文将详细介绍这一方法的使用场景、实现原理及其在实际应用中的价值。 String.prototype.isWellFormed…

Springboot和Es整合

说明&#xff1a;本文章主要是简单整合和简单增删改查。 1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

阀井可燃气体监测仪,开启地下管网安全新篇章-旭华智能

在城市的脉络中&#xff0c;地下管网犹如隐秘的动脉&#xff0c;支撑着现代生活的运转。而在这庞大网络的关键节点上&#xff0c;阀井扮演着不可或缺的角色。然而&#xff0c;由于其密闭性和复杂性&#xff0c;阀井内部一旦发生可燃气体泄漏&#xff0c;将对公共安全构成严重威…

C#中通道(Channels)的应用之(生产者-消费者模式)

一.生产者-消费者模式概述 生产者-消费者模式是一种经典的设计模式&#xff0c;它将数据的生成&#xff08;生产者&#xff09;和处理&#xff08;消费者&#xff09;分离到不同的模块或线程中。这种模式的核心在于一个共享的缓冲区&#xff0c;生产者将数据放入缓冲区&#x…

4.寻找两个正序数组的中位数--力扣

给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,3], nums2 [2] 输出&#xff1a;2.00000 解释&…

2Spark Core

2Spark Core 1.RDD 详解1) 为什么要有 RDD?2) RDD 是什么?3) RDD 主要属性 2.RDD-API1) RDD 的创建方式2) RDD 的算子分类3) Transformation 转换算子4) Action 动作算子 3. RDD 的持久化/缓存4. RDD 容错机制 Checkpoint5. RDD 依赖关系1) 宽窄依赖2) 为什么要设计宽窄依赖 …

面试题刷题

i 或 i 基础几个9&#xff08;评价系统的指标&#xff09; Arrays.aslist 的bug 方法做了重写 这样就能使用了 list的迭代器 不能使用list.remove方法。需要使用迭代器的remove方法 正确操作 Hashcode hashcode是object对象的方法 是一个native方法 hashcode冲突案例和hashcod…

编译pytorch——cuda-toolkit-nvcc

链接 https://blog.csdn.net/wjinjie/article/details/108997692https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#switching-between-driver-module-flavorshttps://forums.developer.nvidia.com/t/can-not-load-nvidia-drivers-on-ubuntu-22-10/239750https://…

Linux网络_套接字_UDP网络_TCP网络

一.UDP网络 1.socket()创建套接字 #include<sys/socket.h> int socket(int domain, int type, int protocol);domain (地址族): AF_INET网络 AF_UNIX本地 AF_INET&#xff1a;IPv4 地址族&#xff0c;适用于 IPv4 协议。用于网络通信AF_INET6&#xff1a;IPv6 地址族&a…

【Go】Go Gorm 详解

1. 概念 Gorm 官网&#xff1a;https://gorm.io/zh_CN/docs/ Gorm&#xff1a;The fantastic ORM library for Golang aims to be developer friendly&#xff0c;这是官网的介绍&#xff0c;简单来说 Gorm 就是一款高性能的 Golang ORM 库&#xff0c;便于开发人员提高效率 那…

51单片机 AT24C02(I2C总线)

存储器 随机存储 RAM 只读存储 ROM AT24C02芯片 是一种可以实现掉电不丢失的存储器&#xff0c;可用于保存单片机运行时想要永久保存的数据信息 存储材质&#xff1a;E2PROM 通讯接口&#xff1a;I2C总线 容量&#xff1a;256字节 I2C总线 一种通用的数据总线 两根通信线…

再见IT!

再见IT 学了三年半前端&#xff0c;今天可能真的要和我最爱的前端说拜拜了&#xff01;没办法大局为重&#xff01; 在这个AI乱飞和短视频风口的时代&#xff0c;只能说当下学习任何一个技术远比2020年学习起来要简单的多。往后技术的发展无疑是飞速的&#xff0c;智能的&…

【开源免费】基于Vue和SpringBoot的人口老龄化社区服务与管理平台(附论文)

本文项目编号 T 140 &#xff0c;文末自助获取源码 \color{red}{T140&#xff0c;文末自助获取源码} T140&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

回归预测 | MATLAB实SVM支持向量机多输入单输出回归预测

效果一览 基本介绍 回归预测 | MATLAB实SVM支持向量机多输入单输出回归预测 …………训练集误差指标………… 1.均方差(MSE)&#xff1a;166116.6814 2.根均方差(RMSE)&#xff1a;407.5741 3.平均绝对误差&#xff08;MAE&#xff09;&#xff1a;302.5888 4.平均相对百分误…

系统学习算法:专题四 前缀和

题目一&#xff1a; 算法原理&#xff1a; 这道题是一维前缀和的模板题&#xff0c;通过这道题我们可以了解什么是前缀和 题意很简单&#xff0c;就是先输入数组个数和查询次数&#xff0c;然后将数组的值放进数组&#xff0c;每次查询给2个数&#xff0c;第一个是起点&#x…

智能科技与共情能力加持,哈曼重新定义驾乘体验

2025年1月6日&#xff0c;拉斯维加斯&#xff0c;2025年国际消费电子展——想象一下&#xff0c;当您步入一辆汽车&#xff0c;它不仅能响应您的指令&#xff0c;更能理解您的需求、适应您的偏好&#xff0c;并为您创造一个独特且专属的交互环境。作为汽车科技领域的知名企业和…