数据结构系列文章—线性结构

线性结构

前言

//嵌入式入门必学,
//文章中用到的Linux版本——Ubuntu18.04
//本文章旨在通过项目程序,掌握线性结构-动态顺序表

什么是数据结构

//数据:现实生活中的一切事物 
​
//结构:逻辑结构和存储结构
​
//研究的是数据的逻辑结构、存储结构及其操作(创销增删改查)

为什么学习数据结构

//学习C语言目的是:写程序
//而学习数据结构的目的是:高效的写程序

结构

逻辑结构

存储结构

顺序存储:
    逻辑上连续的数据,在物理空间上也连续
——(计算机上)
    
链式存储:
    逻辑上连续的数据,在物理空间上不一定连续
——(计算机上)
    
索引存储:
    有索引表,索引表占有一定的空间
    根据索引表找数据,插入数据、删除数据要更新索引表
    索引表本身占空间
    插入数据和删除数据之后要更新索引表,时间开销大,查找方便,插入和删除不方便
——(数据结构上)
    
哈希存储:
    根据关键字就能定位到记录本身,查询方便,插入删除方便
    哈希函数设置的不合理,哈希存储会降维成索引存储
——(数据结构上)

项目

动态顺序表

1、创建目录

创建ListBak目录,包含子目录bin目录、include目录、obj目录、src目录、子文件Makefile文件

详细如下图

2、头文件

myhead.h
#ifndef _MYHEAD_H
#define _MYHEAD_H
//相关的头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//文件相关
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
​
//相关的定义
//定义数据类型
/*
typedef struct student
{
    char name[20];
    char id[20];
    char add[20];
    int age;
}data_type;
 */
//简化操作,将int data_type
typedef int data_type;
//定义顺序表
typedef struct list
{
    data_type *Data;
    int size;
    int count;
}List;
​
//返回值
typedef enum ret{
    /* member*/
    LIST_NULL = -4,
    POS_ERR,
    LIST_FULL,
    LIST_EMPTY,
    OK,
​
} ret_e;
​
//相关函数声明
//打印菜单
//函数返回值:获取的选项
int Menu(void);
​
//函数定义:
//函数功能:创建顺序表
//函数参数:void
//函数返回值:成功返回表的地址,失败返回NULL
List *CreateList(void);
​
//函数功能:插入元素
//函数参数:给谁插入,插入的位置,插入的值
//函数返回值:成功返回OK,失败返回失败原因(错误信息)
int InsertItem(List *pList,int pos,data_type item);
​
​
//函数功能:显示所有的元素
//函数参数:被显示元素的表
//函数返回值:成功返回OK,失败返回失败原因
int ShowList(List *pList);
​
//函数功能:查询元素
//函数参数:查哪个表,表的元素
//函数返回值:成功返回查到的元素,失败返回失败原因
int Search(List *pList,data_type item);
​
//函数功能:删除元素
//函数参数:被删除元素的表,删除的位置,删除的值
//函数返回值:成功返回OK,失败返回失败原因
int DeleteItem(List *pList,int pos,data_type *item);
​
//函数功能:销毁空间
//函数参数:要销毁的表
//函数返回值:成功返回OK,失败返回失败原因
int DestoryList(List **pList);
​
//函数功能:保存
//函数参数:要保存的表
//函数返回值:成功返回OK,失败返回失败原因
int Save(List *pList);
​
//函数功能:导入
//函数参数:
//函数返回值:
List *LoadList(List *pList);
​
//函数功能:修改元素
//函数参数:被修改元素的表,旧元素,新元素
//函数返回值:成功返回OK,失败返回失败原因
int ModifyItem(List *pList,data_type old_item,data_type new_item);
#endif

3、源代码文件

main.c
#include"../include/myhead.h"
​
int main(int argc, const char *argv[])
{
    //表
    List *pList = NULL;
    //定义选项
    int opt = 0;
    //定义插入位置
    int pos = 0;
    //定义插入元素
    data_type item = 0;
    //接返回值
    int ret = 0;
    //定义修改函数旧元素,新元素变量
    data_type old_item = 0;
    data_type new_item = 0;
​
    //打印目录 Menu()
    while(1)
    {
        opt = Menu();
        if(-1 == opt) break;//退出
        switch(opt)
        {
            case 1:
                //insert
                printf("请输入要插入的位置和元素,尾插(pos=-1):");
                scanf("%d%d",&pos,&item);
                ret = InsertItem(pList,pos,item);
                break;
            case 2:
                //delete
                printf("请输入要删除的位置(尾删 -1):");
                scanf("%d",&pos);//小Bug:用户输入5的位置,实际删除6的位置
                ret = DeleteItem(pList,pos,&item);
                if(!ret)    printf("删除的:%d:\n",item);
                break;
            case 3:
                //search
                printf("请输入要查询的元素:");
                scanf("%d",&item);
                ret = Search(pList,item);
                break;
            case 4:
                //modify(修改元素)
                printf("请输入被修改的元素与修改后的元素:");
                scanf("%d %d",&old_item,&new_item);
                ret = ModifyItem(pList,old_item,new_item);
                break;
            case 5:
                //show
                ret = ShowList(pList);
                break;
            case 6:
                //save
                ret = Save(pList);
                break;
            case 7:
                //load
                pList = LoadList(pList);
                break;
            case 8:
                //destory
                printf("main : Before %p\n",pList);
                ret = DestoryList(&pList);
                printf("main : After %p\n",pList);
                break;
            case 9:
                //创建顺序表
                //创建空间
                pList = CreateList();
                if(!pList)  return -1;
                printf("pList = %p\n",pList);
                printf("pList->size = %d\n",pList->size);
                break;
            defaut:
                puts("请输入有效选项!");
        }
        switch(ret)
        {
            case POS_ERR:
                puts("POS_ERR");
                break;
            case LIST_FULL :
                puts("LIST_FULL");
                //调用扩容的函数
                break;
            case LIST_NULL:
                puts("LIST_NULL");
                //重新分配空间
                break;
            case LIST_EMPTY:
                puts("LIST_EMPTY");
                break;
        }
    }
    
    return 0;
}
menu.c
#include"../include/myhead.h"
//打印菜单
//函数返回值:获取的选项
int Menu(void)
{
    int opt = 0;
    puts("\t\t 1-----插入元素");
    puts("\t\t 2-----删除元素");
    puts("\t\t 3-----查询元素");
    puts("\t\t 4-----修改元素");
    puts("\t\t 5-----显示元素");
    puts("\t\t 6-----保存");
    puts("\t\t 7-----导入");
    puts("\t\t 8-----销毁");
    puts("\t\t 9-----创建顺序表");
    puts("\t\t-1-----退出");
    printf("请选择功能:");
    scanf("%d",&opt);
    return opt;
}
insert.c
#include"../include/myhead.h"
​
//函数功能:插入元素
//函数参数:给谁插入,插入的位置,插入的值
//函数返回值:成功返回OK,失败返回失败原因(错误信息)
int InsertItem(List *pList,int pos,data_type item)
{
    //入参判断
    if(!pList) return LIST_NULL;
    //判断是否为满
    if(pList->count == pList->size) return LIST_FULL;
    //判断位置是否合法
    if(pos < -1 || pos > pList->count) return POS_ERR;
    //插入
    //如果 pos = -1 尾插
    if(-1 == pos){
        pList->Data[pList->count] = item;
        //元素个数+1
        pList->count++;
        return OK;
    }
    //
    //1、移动元素
    for(int i = pList->count; i > pos; i--){
        pList->Data[i] = pList->Data[i - 1];
    }
    //2.插入
    pList->Data[pos] = item;
    //3.count
    pList->count ++;
    return OK;
}
delete.c
#include"../include/myhead.h"
//函数功能:删除元素
//函数参数:被删除元素的表,删除的位置,删除的值
//函数返回值:成功返回OK,失败返回失败原因
int DeleteItem(List *pList,int pos,data_type *item)
{
    //入参判断
    if(!pList)  return LIST_NULL;
    //表为空
    if(0 == pList->count) return LIST_EMPTY;
    //pos
    if(pos < -1 || pos > pList->count - 1) return POS_ERR;
    //删除元素
    //尾删
    if(-1 == pos){
        //删的同时把最后一个元素保存
        *item = pList->Data[pList->count-1];
        //元素的个数 -1
        pList->count --;
        puts("成功删除最后一个元素\n");
        return OK;
    }
    //正常的删除
    //1、保存元素
    *item = pList->Data[pos];
    //移动元素
    for(int i = pos; i < pList->count-1; i++){
        pList->Data[i] = pList->Data[i + 1];
    }
    //个数 -1
    pList->count--;
    printf("成功删除%d元素\n",*item);
    return OK;
}
search.c
#include"../include/myhead.h"
​
//函数功能:查询元素
//函数参数:查哪个表,表的元素
//函数返回值:成功返回查到的元素,失败返回失败原因
int Search(List *pList,data_type item)
{
    //入参判断表是否存在
    if(!pList)  return LIST_NULL;
    //判断表是否为空
    if(0 == pList->count) return LIST_EMPTY;
    //遍历元素
    for(int i = 0; i < pList->count; i++){
        if(pList->Data[i] == item){
            //找到了,返回元素的位置
            puts("表中存在此元素");
            return OK;
        }
    }
    //找到了
    puts("表中不存在此元素");
    return OK;
}
modify.c
#include"../include/myhead.h"
//函数功能:修改元素
//函数参数:被修改元素的表,旧元素,新元素
//函数返回值:成功返回OK,失败返回失败原因
int ModifyItem(List *pList,data_type old_item,data_type new_item)
{
    //入参判断
    if(!pList) return LIST_NULL;
    //如果为空
    if(0 == pList->count) return LIST_EMPTY;
    //从头到尾遍历元素
    for(int i = 0; i < pList->count; i++){
        if(pList->Data[i] == old_item){
            //找到了
            //替换
            pList->Data[i] = new_item;
            puts("修改成功");
            return OK;
        }
    }
    //没找到
    puts("查无旧元素");
    return OK;
}
show.c
#include"../include/myhead.h"
​
//函数功能:显示所有的元素
//函数参数:被显示元素的表
//函数返回值:成功返回OK,失败返回失败原因
int ShowList(List *pList)
{
    //入参判断
    //判断有没有这个表
    if(!pList)return LIST_NULL;
    //如果为空
    if(0 == pList->count) return LIST_EMPTY;
    //遍历打印元素
    for(int i = 0; i < pList->count; i++){
        printf("%d\t",pList->Data[i]);
    }
    putchar(10);
    return OK;
}
save.c
#include"../include/myhead.h"
//函数功能:保存
//函数参数:要保存的表
//函数返回值:成功返回OK,失败返回失败原因
int Save(List *pList)
{
    int fd = 0;
    //入入参判断
    if(!pList) return LIST_NULL;
    //打开文件
    fd = open("data.txt",O_WRONLY | O_CREAT | O_TRUNC,0664);
    //写
    write(fd,pList,sizeof(List));
    //写存储
    write(fd,pList->Data,sizeof(data_type) * pList->size);
    //关闭文件
    close(fd);
    puts("Write Success!");
    return OK;
}
load.c
#include"../include/myhead.h"
//函数功能:导入
//函数参数:
//函数返回值:成功返回表的地址,失败返回NULL
List *LoadList(List *pList)
{
    int mysize = 1;
    //创建空间
    //表:用来接收
    pList = (List *)malloc(sizeof(List));
    //判断空间是否开辟成功
    if(!pList){
        puts("MALLOC");
        return NULL;
    }
    memset(pList,0,sizeof(List));
    pList->Data = (data_type *)malloc(sizeof(data_type) * mysize);//大小,显示计算
    pList->size = mysize;
​
    int fd = 0;
    fd = open("data.txt",O_RDONLY);
    if(fd != -1)//成功打开文件,有原始数据
    {
        //读数据,获取size和count
        read(fd,pList,sizeof(List));
        //申请空间
        pList->Data = (data_type *)malloc(sizeof(data_type)* pList->size);
        if(!pList->Data) return NULL;
        //读数据给存储空间
        read(fd,pList->Data,sizeof(data_type)*pList->size);
        close(fd);
        puts("read success!");
        return pList;
    }
}
destory.c
#include"../include/myhead.h"
//函数功能:销毁空间
//函数参数:要销毁的表
//函数返回值:成功返回OK,失败返回失败原因
int DestoryList(List **pList)
{
    //入参判断
    printf("删除之前的地址:%p\n",*pList);
    if(!(*pList)) return LIST_NULL;
    //释放空间
    free(*pList);
    *pList = NULL;
    printf("删除之后的地址:%p\n",*pList);
    return OK;
}
creat.c
#include"../include/myhead.h"
​
//函数定义:
//函数功能:创建顺序表
//函数参数:void
//函数返回值:成功返回表的地址,失败返回NULL
List *CreateList(void)
{
    int mysize = 0;//后续的scanf接收表大小
    List *pList = NULL; //避免野指针的出现
    //创建空间
    //表
    pList = (List *)malloc(sizeof(List));
    //判断空间是否开辟成功,失败打印MALLOC
    if(!pList){
        puts("MALLOC");
        return NULL;//与CreateList函数返回值对应
    }
    //void *memset(void *s, int c, size_t n);
    //s:指向要设置的内存区域的指针。
    //c:要设置的值,会被转换为unsigned char类型。
    //n:要设置的字节数。
    memset(pList,0,sizeof(List));
    //开始创建存储空间的大小
    printf("请输入大小:");
    scanf("%d",&mysize);
    //给顺序表的存储空间
    pList->Data = (data_type *)malloc(sizeof(data_type) * mysize);//大小,显示计算
    //calloc    效率没有malloc高
    //初始化顺序表的大小
    pList->size = mysize;
    return pList;
}

4、Makefile文件

ListBak目录下Makefile文件
All:
    make -C ./src/
    make -C ./obj/
​
.PHONY:CLEAN
CLEAN:
    rm obj/*.o
    rm bin/*
obj目录下Makefile文件
ALL:
    gcc *.o -o ../bin/APP
src目录下Makefile文件
ALL:../obj/main.o ../obj/menu.o ../obj/creat.o ../obj/insert.o ../obj/show.o ../obj/search.o ../obj/delete.o ../obj/destory.o ../obj/save.o ../obj/load.o ../obj/modify.o
../obj/main.o:main.c
    gcc -c $< -o $@
../obj/menu.o:menu.c
    gcc -c $< -o $@
../obj/creat.o:creat.c
    gcc -c $< -o $@
../obj/insert.o:insert.c
    gcc -c $< -o $@
../obj/show.o:show.c
    gcc -c $< -o $@
../obj/search.o:search.c
    gcc -c $< -o $@
../obj/delete.o:delete.c
    gcc -c $< -o $@
../obj/destory.o:destory.c
    gcc -c $< -o $@
../obj/save.o:save.c
    gcc -c $< -o $@
../obj/load.o:load.c
    gcc -c $< -o $@
../obj/modify.o:modify.c
    gcc -c $< -o $@

后续为大家带来全注释版本,持续更新……

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值