尝试模仿现实通讯录

news2024/11/19 3:24:11

学习C语言已有一段时间,我虽不敢说代码水平尚可,但学习一段时间总需要有些成果。下半年开学后,专业课程增多,我需要每天完成学校任务,所花的时间也不算少,但还是有些空闲的。想起自己之前学过用C语言写通讯录,其中功能较为全面,增删查改皆有,且可以直接展示所有已存储的联系人。不过这和我们生活中的用的通讯录还是有些不同的,像批量删除,指定删除等功能,实际上当我自己做起来后才发现其代码量并不少,可能也是因为这个,这些更适合自己摸索着做吧。

我从九月末旬开始创建文件,做完整的通讯录,自己想一些功能,并让朋友也想一些要实现的功能,这里面就有熟悉的长按删除,当然我是做不出来的,以及其他一些我能力达不到的功能,我觉得这毕竟涉及真正一个应用的完成,我也只是用自己平庸的C语言水平来展现功能实现的过程罢了。整体思路并不是很简洁,因为我看到为了一个功能而写的代码很多,另一个方面就是,我没见到过真正大量的代码是什么样子......

最近我才开始接触初阶数据结构,就在里面写了些注释,是自己对这个函数时、空间复杂度的分析,所以这肯定有错。另外,整个通讯录并没有完成,你可以看到我在初始化时就加载进了文件,但是这个程序还不能代码式地退出。对于里面的变量我已经注释了其用处,应该可以读明白。这个通讯录拖沓了很久,我必须承认我的懒惰在起作用。整个通讯录所呈现的我的编程思路我自认为只能作为一个基础水平的思路,还有很多可改变之处。今天是1024程序员节,且希望各位看官能看个爽吧。

头文件project.h

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100
#define NAME 20//姓名
#define SEX 7//性别
#define ADDRESS 20//地址
#define OCC 10//职业
#define NUMBER 15//电话
#define CP 20//动态开辟的空间
#define ADD_SZ 10//增容时所用
#define RS 30
#define LS 40//最多可选择删除的数量

struct PeoInfo
{
    char name[NAME];
    char sex[SEX];
    char address[ADDRESS];
    char occ[OCC];
    char number[NUMBER];
    int age;
};

struct Contact
{
    struct PeoInfo* data;
    int sz;
    int capacity;
};

void InitContact(struct Contact* ps);

void LoadContact(struct Contact* ps);

void AddContact(struct Contact* ps);

void DelContact(struct Contact* ps);

void ChaContact(const struct Contact* ps);

void SortContact(const struct Contact* ps);

void ModifyContact(const struct Contact* ps);

void ShowContact(const struct Contact* ps);

int SearchContact(const struct Contact* ps);

project2.c

 

 

 

 

 

 

 

 

 

#include "project.h"

int r = 0;//回收站的sz
int rt = RS;//回收站的capacity
int pl[LS];//批量删除用来存储序号
int l = 0;//批量删除存储序号数

int z = 0;//泛用性··

static int FindByName(char name[], const struct Contact* pf)//时间O(N/2), 空间O(1)
{
    assert(name && pf);
    int i = 0;
    for (i = 0; i < pf->sz; i++)
    {
        if (0 == strcmp(pf->data[i].name, name))
        {
            return i;
        }
    }
    return -1;
}

static int check_capacity(struct Contact* ps)//时间O(1), 空间O(ADD_SZ)
{
    assert(ps);
    if (ps->sz == ps->capacity)
    {
        struct PeoInfo* ptr = (struct PeoInfo*)realloc(ps->data, (ps->capacity + ADD_SZ) * sizeof(struct PeoInfo));
        if (ptr != NULL)
        {
            ps->data = ptr;
            ps->capacity += ADD_SZ;
            printf("增容成功\n");
            return 1;
        }
        else
        {
            perror("AddContact()");
            return 0;
        }
    }
    else
        return 1;
}

static int Hsz(struct PeoInfo* rs)//时间O(1), 空间O(ADD_SZ)
{
    struct PeoInfo* ptr = (struct PeoInfo*)realloc(rs, (r + ADD_SZ) * sizeof(struct PeoInfo));
    if (ptr != NULL)
    {
        rs = ptr;
        rt += ADD_SZ;
        printf("增容成功\n");
        return 1;
    }
    else
    {
        perror("ZDDel()");
        return 0;
    }
}

void LoadContact(struct Contact* ps)//时间O(ps->sz), 空间O(ps->sz)
{
    FILE* pfr = fopen("E://txl.txt", "r");
    if (pfr == NULL)
    {
        perror("LoadContact::fopen");
        return;
    }
    struct PeoInfo ptr = { 0 };
    while (fread(&ptr, sizeof(struct PeoInfo), 1, pfr))
    {
        //检查是否要增容
        check_capacity(ps);
        ps->data[ps->sz] = ptr;
        ps->sz++;
    }
    fclose(pfr);
    pfr = NULL;
}

void InitContact(struct Contact* ps)//时间O(1), 空间O(CP)
{
    assert(ps);
    ps->data = (struct PeoInfo*)malloc(CP * sizeof(struct PeoInfo));
    if (ps->data == NULL)
    {
        perror("InitContact()");
        return;
    }
    ps->sz = 0;
    ps->capacity = CP;
    LoadContact(ps);
}

void AddContact(struct Contact* ps)//时间O(1), 空间O(1)
{
    assert(ps);
    if (0 == check_capacity(ps))
    {
        return;
    }
    else
    {
        printf("请输入要添加的名字:>");
        scanf("%s", ps->data[ps->sz].name);
        printf("请输入要添加的性别:>");
        scanf("%s", ps->data[ps->sz].sex);
        printf("请输入要添加的电话号码:>");
        scanf("%s", ps->data[ps->sz].number);
        printf("请输入要添加的地址:>");
        scanf("%s", ps->data[ps->sz].address);
        printf("请输入要添加的职业:>");
        scanf("%s", ps->data[ps->sz].occ);
        printf("请输入要添加的年龄:>");
        scanf("%d", &ps->data[ps->sz].age);
        ps->sz++;
        printf("已成功添加第%d个联系人\n", ps->sz);
    }
}

static int ZDDel(struct Contact* pz, struct PeoInfo* rs)//时间O(pz->sz - 1 - m), 空间O(3)
{
    assert(pz);
    assert(rs);
    int j = 0;
    int i = 0;
    char name[NAME];//存储要操作的名字
    if (r + 1 == rt)
    {
        i = Hsz(rs);
        if (1 == i)
            ;
        else
        {
            printf("虚拟回收站扩容失败,请重新进行删除\n");
            return 1;
        }
    }
    printf("请输入要删除人的名字: >");
    scanf("%s", &name[z]);
    int m = FindByName(name, pz);
    if (m == -1)
    {
        printf("要删除的人不存在\n");
        return 3;
    }
    else
    {
        FILE* hsz = fopen("E://hsz.txt", "w");
        if (hsz == NULL)
        {
            perror("ZDDel::fopen");
            printf("文件创建失败,请重新进行删除\n");
            return 2;
        }
        fwrite(pz->data + m, sizeof(struct PeoInfo*), 1, hsz + z);
        z++;//name数组的下标,如果为0,添入1个,则变为1
        fclose(hsz);
        hsz = NULL;
        *(rs + r) = pz->data[m];
        r++;
        if (r + 1 == rt)
        {
            i = Hsz(rs);
            if (1 == i)
                ;
            else if (2 == i)
                ;
            else
            {
                printf("虚拟回收站扩容失败,请重新进行删除\n");
                return 1;
            }
        }
        else
            ;
        for (j = m; j < pz->sz - 1 - m; j++)
        {
            pz->data[j] = pz->data[j + 1];
        }
        pz->sz--;
        printf("成功删除指定联系人\n");
    }
    return 0;
}

static int PLDel(struct Contact* pp, struct PeoInfo* rs)
{
    assert(pp);
    int i = 0;
    int j = 0;
    int n = 0;
    int m = 0;
    int o = 0;
    struct PeoInfo* tmp = (struct PeoInfo*)calloc(10, sizeof(struct PeoInfo));
    if (r + 1 == rt)
    {
        j = Hsz(rs);
        if (1 == j)
            ;
        else if (2 == j)
            ;
        else
        {
            printf("虚拟回收站扩容失败,请重新进行删除\n");
            return 1;
        }
    }
    printf("选择结束后写入666来进行下一步\n");
    printf("请选择要删除的序列号: >");
    while (i <= LS)
    {
        scanf("%d", &pl[i]);
        l++;
        i++;
        if (i == LS)
        {
            printf("最多选择%d个!\n", LS);
            printf("是否确定删除? 1.确定  2.取消\n");
            scanf("%d", &n);
            if (1 == n)
            {
                FILE* hsz = fopen("E://hsz.txt", "w");
                if (hsz == NULL)
                {
                    perror("ZDDel::fopen");
                    printf("文件创建失败,请重新进行删除\n");
                    printf("已将选中的序列号保存\n");
                    return 2;
                }
                struct PeoInfo* pld = (struct PeoInfo*)calloc(LS , sizeof(struct PeoInfo));
                for (o = 0; o < i; o++)
                {
                    fwrite(pp->data + (pl[o]), sizeof(struct PeoInfo*), 1, hsz + z);
                    *(pp->data + (pl[o])) = *(pld + o);
                    z++;
                }
                fclose(hsz);
                hsz = NULL;
                SortContact(pp);
                for (i; i >= 0; i--)
                {
                    pl[i] = 0;
                }
                printf("删除成功\n");
            }
            else
            {
                printf("已将选中的序列号保存\n");
                return 2;
            }
        }
        else if (666 == pl[i - 1])
        {
            printf("是否确定删除? 1.确定  2.取消\n");
            scanf("%d", &n);
            if (1 == n)
            {
                FILE* hsz = fopen("E://hsz.txt", "w");
                if (hsz == NULL)
                {
                    perror("ZDDel::fopen");
                    printf("文件创建失败,请重新进行删除\n");
                    printf("已将选中的序列号保存\n");
                    return 2;
                }
                struct PeoInfo* pld = (struct PeoInfo*)calloc(LS, sizeof(struct PeoInfo));
                for (o = 0; o < i; o++)
                {
                    fwrite(pp->data + (pl[o]), sizeof(struct PeoInfo*), 1, hsz + z);
                    *(pp->data + (pl[o])) = *(pld + o);
                    z++;
                }
                fclose(hsz);
                hsz = NULL;
                //SortContact(pp);
                for (o = 0; o < i; o++)
                {
                    pl[o] = 0;
                }
                printf("删除成功\n");
            }
            else
            {
                printf("已将选中的序列号保存\n");
                return 2;
            }
        }
        //continue;
    }
    return 0;
}


void DelContact(struct Contact* ps)//时间O(1), 空间O(RS)
{
    assert(ps);
    int a = 0;
    int c = 0;
    int b = 0;
    int d = 0;
    int e = 1;
    int i = 0;
    char ret[20] = "0";
    struct PeoInfo* rs = (struct PeoInfo*)malloc(RS * sizeof(struct PeoInfo));
    if (rs == NULL)
    {
        perror("DelContact()");
    }
    printf("选择批量删除前请查询可用的序列号.是否查询?\n");
    while (scanf("%s", ret) != EOF)
    {
        if (0 == strcmp("是", ret))
        {
            ShowContact(ps);
            break;
        }
        else if (0 == strcmp("否", ret))
            break;
        else
        {
            printf("请重新输入!\n");
            for (i = 0; i < 20; i++)
            {
                ret[i] = '0';
            }
            continue;
        }
    }
    printf("请选择删除模式: 1、指定删除  2、批量删除\n");
    while (scanf("%d", &a) != EOF)
    {
        if (a == 1)
        {
            while (e)
            {
                e = ZDDel(ps, rs);
            }
            break;
        }
        else if (a == 2)
        {
            c = PLDel(ps, rs);
            if (1 == c)//返回1意味着删除成功
                return;
            else if (2 == c)//返回2意味着选中了但是取消删除了或者开辟空间啥的失败了
            {
                printf("是否查看已选中的序列号? 1、是  2、否\n");
                scanf("%d", &b);
                if (1 == b)
                {
                    int i = 0;
                    for (i = 0; i < l; i++)
                    {
                        printf("%d ", pl[i]);
                    }
                    return;
                }
                else
                {
                    printf("已退出删除界面\n");
                    return;
                }
            }
            else
                return;
        }
        else
        {
            printf("请重新输入\n");
            continue;
        }
    }
}

void ChaContact(const struct Contact* ps)
{
    assert(ps);
    char name[NAME];
    printf("请输入要查找的名字: >");
    while (scanf("%s", name) != EOF)
    {
        int ret = FindByName(name, ps);
        if (ret == -1)
            printf("要查找的人不存在\n");
        else
        {
            printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5s\n", "姓名", "性别", "地址", "职业", "号码", "年龄");
            printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5d\n", ps->data[ret].name,
                ps->data[ret].sex,
                ps->data[ret].address,
                ps->data[ret].occ,
                ps->data[ret].number,
                ps->data[ret].age);
        }
        break;
    }
}

void ModifyContact(const struct Contact* ps)
{
    printf("请输入要修改人的名字:>");
    char name[NAME];
    scanf("%s", name);
    int ret = FindByName(name, ps);
    if (ret == -1)
        printf("要修改的人不存在\n");
    else
    {
        printf("请输入要修改的名字:>");
        scanf("%s", ps->data[ret].name);
        printf("请输入要修改的性别:>");
        scanf("%s", ps->data[ret].sex);
        printf("请输入要修改的电话号码:>");
        scanf("%s", ps->data[ret].number);
        printf("请输入要修改的地址:>");
        scanf("%s", ps->data[ret].address);
        printf("请输入要修改的职业:>");
        scanf("%s", ps->data[ret].occ);
        printf("请输入要修改的年龄:>");
        scanf("%d", &ps->data[ret].age);
        printf("修改成功\n");
    }
}

void ShowContact(const struct Contact* ps)
{
    int i = 0;
    printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5s\n", "姓名", "性别", "地址", "职业", "号码", "年龄");
    for (i = 0; i < ps->sz; i++)
    {
        printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5d\n", ps->data[i].name,
            ps->data[i].sex,
            ps->data[i].address,
            ps->data[i].occ,
            ps->data[i].number,
            ps->data[i].age);
    }
}

int CmpByName(const void* q1, const void* q2)
{
    return strcmp(((struct PeoInfo*)q1)->name, ((struct PeoInfo*)q2)->name);
}

void SortContact(const struct Contact* ps)
{
    qsort(ps->data, ps->sz, sizeof(struct PeoInfo), CmpByName);
}

int SearchContact(const struct Contact* ps)
{
    assert(ps);
    char name[NAME];
    printf("请输入要搜索的名字: >");
    scanf("%s", name);
    int ret = FindByName(name, ps);
    if (ret == -1)
    {
        printf("要搜索的人不存在\n");
        return ret;
    }
    else
    {
        printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5s\n", "姓名", "性别", "地址", "职业", "号码", "年龄");
        printf("%-9s\t%-7s\t%-10s\t%-10s\t%-15s\t%5d\n", ps->data[ret].name,
            ps->data[ret].sex,
            ps->data[ret].address,
            ps->data[ret].occ,
            ps->data[ret].number,
            ps->data[ret].age);
    }
    return 0;
}
 

主文件project1.c

#include "project.h"


void menu()
{
    printf("\n");
    printf("*************************************\n");
    printf("*******   1. 增加   2. 删除   *******\n");
    printf("*******   3. 查找   4. 修改   *******\n");
    printf("*******   5. 展示   6. 排序   *******\n");
    printf("*******   7. 搜索   0. 退出   *******\n");
    printf("*************************************\n");
    printf("\n");
}

enum Options
{
    Exit,
    Add,
    Del,
    Cha,
    Mdf,
    Show,
    Sort,
    Sea,
};

int main()
{
    int a1 = 0;
    int input = 0;
    struct Contact txl;
    InitContact(&txl);
    do
    {
        menu();
        printf("请选择: >");
        scanf("%d", &input);
        switch (input)
        {
        case Add:
            AddContact(&txl);
            break;
            /*if (a1 == 0)
            {
                printf("添加失败, 请重试\n");
                break;
            }
            else
            {
                printf("新添加的联系人是第%d个联系人\n", a1);
                break;
            }*/
        case Del:
            DelContact(&txl);
            break;
        case Cha:
            ChaContact(&txl);
            break;
        case Mdf:
            ModifyContact(&txl);
            break;
        case Show:
            ShowContact(&txl);
            break;
        case Sort:
            SortContact(&txl);
            break;
        case Sea:
            SearchContact("&txl");
            break;
        }
    } while (input);
    return 0;
}

 

到现在为止,我还是没有把批量删除功能做完美。在选择确定删除后,图标会闪烁一会儿然后直接退出整个通讯录。

写一篇放在这里,也是记录一下10月24号我的通讯录记录,以防之后再拿出来写的时候忘记各个变量的作用。

结束。

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

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

相关文章

小程序开发必备功能的吐血整理【个人中心界面样式大全】

&#x1f4cc;个人主页&#xff1a;个人主页 ​&#x1f9c0; 推荐专栏&#xff1a;小程序开发成神之路 --(这是一个为想要入门和进阶小程序开发专门开启的精品专栏&#xff01;从个人到商业的全套开发教程&#xff0c;实打实的干货分享&#xff0c;确定不来看看&#xff1f; &…

FPGA学习笔记(七)verilog的深入学习之任务与函数(语法篇3)

目录任务与函数任务任务的基本概况自动&#xff08;可重入&#xff09;任务函数函数概述自动&#xff08;递归&#xff09;函数常量函数带符号函数条件编译在之前学习的基础上&#xff0c;继续加深对Verilog HDl的学习 前两个见&#xff1a; FPGA学习笔记&#xff08;二&#…

深度学习(python)——神经网络(Artificial Neural Networks)激活函数代码

目录 1.概述 2.激活函数 &#xff08;1&#xff09;基本概念 &#xff08;2&#xff09;sigmoid函数&#xff08;常用&#xff09; 代码(sigmoid) &#xff08;3&#xff09;阶跃函数 代码&#xff08;阶跃函数&#xff09; &#xff08;4&#xff09;ReLU函数&#xff08;目…

【零基础算法】C语言实现二叉搜索树

目录 一&#xff0c;定义 二&#xff0c;性质 三&#xff0c;基本操作 1&#xff0c;初始化 2&#xff0c;查找 3&#xff0c;插入&#xff08;建树&#xff09; 4.删除结点 四&#xff0c;总结 一&#xff0c;定义 二叉查找树&#xff08;Binary Search Tree&#…

记一次网络安全渗透测试实战指南

1.信息收集 网址已无法访问&#xff0c;就不贴了 可以使用Fofa&#xff0c;火线&#xff0c;zoomeye&#xff0c;searchcode.com等爬取相关的资产&#xff0c;重点关注一些有漏洞暴露的框架和服务例如&#xff1a;泛微&#xff0c;PHP&#xff0c;Tomca&#xff0c;后台&#x…

71.(后端)角色接口携带权限数据——flask两张表之间多对多关系的使用与层级关系的输出

1.ORM关系之多对多 1.1 什么时候使用多对多关系 例如&#xff0c;我们我们的项目中&#xff0c;一个用户可以拥有多个角色&#xff0c;同样的&#xff0c;一个角色可以给多个用户。通俗来说&#xff0c;一个用户可以购买多个商品&#xff0c;多个商品可以被一个用户购买 1.2…

【FPGA】Verilog编程实现SDRAM读写(一) ----- 初始SDRAM

文章目录一. 存储器及SDRAM分类1. 存储器分类2. 半导体存储器分类3. SDRAM分类二. 什么是SDRAM&#xff1f;1. SDRAM基本概念2. SDRAM存储阵列3. SDRAM基本存储单元4. BANK概念5. SDRAM容量计算6. SDRAM功能框图7. SDRAM信号引脚8. SDRAM操作命令8.1 禁止命令&#xff08; INHI…

mysql做查询时,第一次很慢,第二三次就会很快?

前言 sql语句第一次查询慢的原因不仅仅是因为执行计划没有被缓存这么简单,有时候你会发现sql语句重用了执行计划,但是第一次查询时还是很慢. 最主要的原因是第一次查询的时候,mysql会将查询出的部分数据和索引从磁盘加载到内存作为缓存,而第二三此查询的时候就直接从内存缓存…

Spring - 手把手分析 IoC 容器创建过程

概述 这里我们以 Spring 5.2.8.RELEASE 版本为例&#xff0c;看一下 IoC 容器 的创建过程。同时我们使用 java-based 的方式实例化 IoC 容器&#xff0c;即使用 AnnotationConfigApplicationContext Configuration 的方式配置容器需要的组件。 ApplicationContext ctx new …

【云IDE初体验】与君相逢恨晚,真正的轻量级开发工具

云IDE产品介绍 云IDE使用教程 免费使用地址&#xff1a;点击【云IDE】&#xff0c;即可开始创建工作空间啦~ 云IDE1.云IDE介绍2. 使用流程3. 体验总结作为一名大学生&#xff0c;学习的地点很关键&#xff0c;尤其是我们计算机系&#xff0c;更是离不开电脑&#xff0c;去图书馆…

调度线程池 ScheduledThreadPoolExecutor 的正确使用姿势

前言 项目中经常会遇到一些非分布式的调度任务&#xff0c;需要在未来的某个时刻周期性执行。实现这样的功能&#xff0c;我们有多种方式可以选择&#xff1a; Timer类&#xff0c; jdk1.3 引入&#xff0c;不推荐 它所有任务都是串行执行的&#xff0c;同一时间只能有一个任…

【C语言】移位操作符 位操作符 - 对二进制位进行精准操作【+面试题目】_[初阶篇]

快速导航 【前言】 1.移位操作符 1.1左移操作符(<<) 1.2右移操作符(>>) 2.位操作符 2.1 & 按位与 2.2 | (按位或) 2.3 ^ (按位异或) 3.面试题目 3.1 交换两个变量&#xff08;不创建临时变量&#xff09; 3.2统计二进制中1的个数 3.2.1 方法一&#xff1a;…

复合事件归因分析

1 复合事件 1.1 概述 1.2 类型 1.2.1 先决条件事件&#xff08;preconditioned events&#xff09; 1.2.2 多变量事件&#xff08;multivariate CEs&#xff09; eg.高温干旱 1.2.3 时间复合事件&#xff08;temporally CEs&#xff09; eg.旱涝急转 1.2.4 空间复合事件…

电子电路设计基本概念100问(二)【学习目标:原理图、PCB、阻抗设计、电子设计基本原则、基本原器件等】

笔者电子信息专业硕士毕业&#xff0c;获得过多次电子设计大赛、大学生智能车、数学建模国奖&#xff0c;现就职于南京某半导体芯片公司&#xff0c;从事硬件研发&#xff0c;电路设计研究。对于学电子的小伙伴&#xff0c;深知入门的不易&#xff0c;特开次博客交流分享经验&a…

【每天学习一点新知识】网络安全--拒绝服务攻击

目录 1、SYN泛洪攻击 SYN泛洪攻击原理 攻击过程 防御机制 2、Smurf攻击 Smurf攻击原理 间接攻击 放大攻击 防御机制 3、DDoS DDoS原理 直接DDoS攻击 间接DDoS攻击 防御机制 1、SYN泛洪攻击 SYN泛洪攻击原理 终端访问Web服务器之前需要和服务器之间建立TCP连接。W…

万字长文解析Scaled YOLOv4模型(YOLO变体模型)

一&#xff0c;Scaled YOLOv4 摘要1&#xff0c;介绍2&#xff0c;相关工作 2.1&#xff0c;模型缩放 3&#xff0c;模型缩放原则 3.1&#xff0c;模型缩放的常规原则3.2&#xff0c;为低端设备缩放的tiny模型3.3&#xff0c;为高端设备缩放的Large模型 4&#xff0c;Scaled-YO…

大学毕业后,我就送了2个月外卖,哭了一整晚

先简单介绍一下自己&#xff0c;我来自湛江&#xff0c;大学学的的物流管理专业&#xff0c;现在就职于一家互联网公司&#xff0c;从事软件测试工作。 我来自湛江的一个偏远农村&#xff0c;家里兄弟姐妹多&#xff0c;父母无力负担我的学费&#xff0c;很多时候学费都是靠姐…

红黑树 - c++

文章目录&#xff1a;红黑树的介绍红黑树节点定义红黑树的插入操作红黑树的删除红黑树的验证红黑树 vs AVL树红黑树的介绍 红黑树(Red-Black-Tree)&#xff0c;通常写为 R-B Tree。它是一种特殊的二叉搜索树。红黑树的每个节点上都有一个存储位来标识节点的颜色&#xff0c;可…

积木报表—JimuReport v1.5.4版本发布,免费的可视化Web报表工具

项目介绍 一款免费的低代码可视化报表&#xff0c;像搭建积木一样在线拖拽设计&#xff01;低代码开发必备&#xff0c;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; 秉承“简单、易用、专业”的产品理念&#xff0c;极大的降低报表开发难度、缩…

【css伪类选择器及透明度——附项目图片及代码】

不知不觉&#xff0c;又鸽了好长时间了&#xff0c;非常抱歉&#xff0c;没办法&#xff0c;毕竟开学了&#xff0c;今天课少&#xff0c;抽出了两个小时写了一篇css的&#xff0c;每天不是被催更&#xff0c;就是在催更的路上。放心&#xff0c;小陈陈有时间一定会给大家分享好…