数据结构——基于顺序表实现通讯录

一、. 基于动态顺序表实现通讯录

1.1  功能要求

1)⾄少能够存储100个⼈的通讯信息

2)能够保存⽤⼾信息:名字、性别、年龄、电话、地址等
3)增加联系⼈信息
4)删除指定联系⼈
5)查找制定联系⼈
6)修改指定联系⼈
7)显⽰联系⼈信息

1.2   思路分析

我们之前创建的顺序表可以实现连续存储数据(类型可以为整型、字符等),但无论是哪种类型,存储信息都比较单一,但是通讯录存储信息比较多,有联系人姓名、性别、年龄等,所以我们把一个联系人的所有信息作为一个整体存储到顺序表,原来我们写的是整型作为数据存储每个数组元素空间,现在转化通讯录,把一个人的所有信息打包变为结构体然后存储到数组元素元素的空间,然后基于顺序表实现通讯录功能。

1.3 通讯录的实现

因为我们是基于顺序表实现通讯录,先将顺序表写好

1.3.1 顺序表

1.3.1.1  SeqList.h
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
//#include"Contact.h"
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_AMX 20
struct ContactInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_AMX];
};
typedef struct ContactInfo  SLDateType;
typedef struct SeqList
{SLDateType* a;int size;//空间有效数据int capacity;//空间大小
}SL;//初始化和销毁
void SLInit(SL* ps);
void SLDestory(SL* ps);//尾插和头插
void SLPushBack(SL* ps, SLDateType x);
void SLPushFront(SL* ps, SLDateType x);
//void SLPrint(SL* ps);//头删和尾删
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//在指定位置之前插入
void SLInsert(SL* ps, int pos, SLDateType x);
//删除指定位置
void SLDel(SL* ps, int pos);

注:这里值得注意的是我们将通讯信息结构体定义在SeqList.h中,然后重命名,后面的顺序表结构也是这样,那为什么不把通讯信息结构体定义在Contact.h,然后再SeqList.h中包含Contact.h,对typedef struct ContactInfo  SLDateType

这样看似没问题,实际会造成重命名的问题,所以我们字书时要规范。

输出结果:

1.3.1.2  SeqList.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
void SLInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}
void SLDestory(SL* ps)
{if (ps->a)free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}
int  SLCheckCapacity(SL* ps)
{assert(ps);int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;if (ps->size == ps->capacity)//进行扩容{SLDateType* ret = (SLDateType*)realloc(ps->a, newcapacity * sizeof(SLDateType));if (ret == NULL){perror("realloc fail:");return 1;}ps->a = ret;ps->capacity = newcapacity;}
}void SLPushBack(SL* ps, SLDateType x)//1.若空间足够,进行插入  2.若空间不够,进行扩容(以1.5或2倍原来大小进行扩容)
{assert(ps);SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//void SLPrint(SL* ps)
//{
//	assert(ps);
//	for (size_t i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->a[i]);
//	}
//	printf("\n");
//}
void SLPushFront(SL* ps, SLDateType x)
{assert(ps);SLCheckCapacity(ps);for (size_t i = ps->size; i > 0; i--){ps->a[i] = ps->a[i-1];}ps->a[0] = x;ps->size++;
}bool SLIsEmpty(SL * ps)//若返回值为假,则有数据,反之,则无
{assert(ps);return ps->size == 0;
}
void SLPopBack(SL* ps)
{assert(ps);//还需要判断是否有数据assert(!SLIsEmpty(ps));ps->size--;
}
void SLPopFront(SL* ps)
{assert(ps);//还需要判断是否有数据assert(!SLIsEmpty(ps));for (size_t i = 0; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}// 在指定位置之前插入
void SLInsert(SL* ps, int pos, SLDateType x)
{assert(ps);SLCheckCapacity(ps);//防止越界访问assert(pos>= 0 && pos<= ps->size);//端点位置为头插和尾插for (size_t i = ps->size; i >pos; i--){ps->a[i] = ps->a[i - 1];}ps->a[pos] = x;ps->size++;
}
//删除指定位置
void SLDel(SL* ps, int pos)
{assert(ps);assert(!SLIsEmpty(ps));assert(pos>= 0 && pos< ps->size);//端点位置为头删和尾删for (size_t i = pos; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

1.3.2  通讯录的初始化+销毁

1.3.2.1 Contact.h
#define _CRT_SECURE_NO_WARNINGStypedef  struct ContactInfo CInfo;
typedef struct SeqList Contact;//将顺序表重命名为通讯录(这里只是声明,无需包含Seqlist.h)//通讯录的初始化和销毁
void ContactInit(Contact* con);
void ContactDestroy(Contact* con);

注:这里没有包含SeqList.h,为什么可以重定义结构体和顺序表呢?

因为这里我们只是声明,没有使用,当在text.c使用时,它就会将Contact.h的CInfo和Contact

展开。

 1.3.2.2 Contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
#include"SeqList.h"
#include <stdlib.h>
#include<stdio.h>
#include<assert.h>
void ContactInit(Contact* con)
{SLInit(con);
}
void ContactDestroy(Contact* con)
{SLDestory(con);
}

这里直接借用顺序表实现

1.3.3   通讯录的添加+删除

1.3.3.1 Contact.h
//通讯录的初始化和销毁
void ContactInit(Contact* con);
void ContactDestroy(Contact* con);
1.3.3.2 Contact.c
void ContactAdd(Contact* con)
{assert(con);CInfo info;printf("请输入姓名:\n");scanf("%s", info.name);printf("请输入性别:\n");scanf("%s", info.sex);printf("请输入年龄:\n");scanf("%d", &info.age);printf("请输入电话号码:\n");scanf("%s", info.tel);printf("请输入地址:\n");scanf("%s", info.addr);//将数据进行尾插SLPushBack(con,info);}
int FindByName(Contact* con,char name[])
{for (int i = 0; i < con->size; i++){if (strcmp(con->a[i].name, name)==0){return i;}}return -1;
}void ContactDel(Contact* con)
{assert(con);char name[NAME_MAX];printf("需要删除的姓名:\n");scanf("%s", name);//先查找该信息位置int ret=FindByName(con,name);if (ret < 0){printf("没找到该联系人\n");return 1;}SLDel(con, ret);//删除指定位置
}

注: info.name这个是数组名,所以不用取地址

1.3.4  查看通讯录 

1.3.4.1 Contact.h
//查看通讯录
void ContactShow(Contact* con);
1.3.4.2  Contact.c
void ContactShow(Contact* con)
{assert(con);assert(con->a);printf("%-4s%-4s%-4s%-4s%-4s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < con->size;i++){printf("%-4s %-4s %-4d%-4s%-4s\n",con->a[i].name, con->a[i].sex, con->a[i].age, con->a[i].tel, con->a[i].addr);}
}

1.3.5  修改通讯录

1.3.5.1 Contact.h
//修改通讯录
void ContactChange(Contact* con);
1.3.5.2 Contact.c
void ContactChange(Contact* con)
{assert(con);char name[NAME_MAX];printf("需要修改的姓名:\n");scanf("%s",name);//先查找该信息位置int ret = FindByName(con, name);if (ret < 0){printf("没找到该联系人\n");return 1;}printf("请输入修改的姓名:\n");scanf("%s",con->a[ret].name);printf("请输入修改的性别:\n");scanf("%s", con->a[ret].sex);printf("请输入修改的年龄:\n");scanf("%d", &con->a[ret].age);printf("请输入修改的电话号码:\n");scanf("%s", con->a[ret].tel);printf("请输入修改的地址:\n");scanf("%s", con->a[ret].addr);printf("修改成功!\n");}

1.3.6 查找指定联系人 

1.3.6.1 Contact.h
//查找指定联系人
void ContactFind(Contact* con);
1.3.6.2 Contact.c
void ContactFind(Contact* con)
{assert(con);char name[NAME_MAX];printf("需要查找的姓名:\n");scanf("%s", name);//先查找该信息位置int ret = FindByName(con, name);if (ret < 0){printf("没找到该联系人\n");return 1;}printf("%-4s%-4s%-4d%-4s%-4s\n",con->a[ret].name, con->a[ret].sex, con->a[ret].age, con->a[ret].tel, con->a[ret].addr);
}

1.3.7 菜单界面

为方便调用通讯录的各种功能,我们做一个菜单界面

1.3.7 .1 text.c
void menu()
{ printf("******************    通讯录   **********************\n");printf("***   1.添加联系人          2.删除联系人       ******\n");printf("***   3.修改通讯录          4.查看指定联系人   ******\n");printf("***   5.查看通讯录          0.退出通讯录       ******\n");printf("*****************************************************\n");}
int main()
{int n = -1;Contact con;ContactInit(&con);do{menu();printf("请输入你的选择;\n");scanf("%d", &n);switch (n){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactChange(&con);break;case 4:ContactFind(&con);break;case 5:ContactShow(&con);break;case 0:break;default:printf("输入错误,请从新输入!\n");break;}}while (n);ContactDestroy(&con);return 0;
}

1.3.8  测试界面

 

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

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

相关文章

ES 未分片 导致集群状态飘红

GET /_cluster/allocation/explain ALLOCATION_FAILED&#xff1a;由于分片分配失败而未分配。 CLUSTER_RECOVERED&#xff1a;由于集群恢复而未分配。 DANGLING_INDEX_IMPORTED&#xff1a;由于导入了悬空索引导致未分配。 EXISTING_INDEX_RESTORED&#xff1a;由于恢复为已关…

vuepress 打包后左侧菜单链接 404 问题解决办法

背景 上周看到一本开源书 《深入架构原理与实践》&#xff0c;是基于 vuepress 搭建的&#xff0c;下载了源码&#xff0c;本地部署了一下&#xff0c;本文记录如何打包该源码遇到的路径问题及思考。 结论&#xff1a; vuepress 插件的 sideBar 的菜单路径默认是相对 / 的&am…

FPGA高端项目:图像缩放+GTP+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案我这里已有的图像处理方案 3、设计思路框架设计框图视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择…

【Java 进阶篇】MVC 模式

欢迎来到本篇详细解释 MVC&#xff08;Model-View-Controller&#xff09;设计模式的教程。MVC 是一种用于组织应用程序的设计模式&#xff0c;有助于将应用程序分成不同的部分&#xff0c;以提高代码的可维护性和可扩展性。在本文中&#xff0c;我们将深入研究 MVC 模式&#…

Vue的详细知识点梳理

Vue.js是一个渐进式的JavaScript框架,被设计用来构建用户界面。 Vue.js的详细知识点梳理: Vue.js的基本特性:包括响应式数据绑定、组件化、模板语法等。 Vue的生命周期:包括创建前、创建、挂载、更新、销毁等阶段,每个阶段都有相应的钩子函数可以使用。 Vue的指令:包括…

SpringBoot整合定时任务遇到的多实例问题

唠嗑部分 是这样&#xff0c;前几日完善了定时任务的日志记录&#xff0c;今日切换了服务器&#xff0c;多部署了一个节点&#xff0c;使用nginx负载均衡&#xff0c;但是查看日志却发现了如下情况 那糟糕了&#xff0c;传说中的多实例问题出现了&#xff0c;今天我们就来聊聊…

stable diffusion安装踩坑之clip安装、git报错

clip本地安装环境链接问题 本节主要记录一下在windows安装stable diffusion时&#xff0c;clip脚本安装不上&#xff0c;本地安装时如何链接到当前库的问题 首先&#xff0c;在脚本安装clip不成功时&#xff0c;脚本会输出一个commend指令&#xff0c;复制到浏览器就可以很快…

虚幻引擎 5.1 中全新的增强型输入操作系统

教程链接 https://www.youtube.com/watch?vCYiHNbAIp4s 前提 虚幻引擎5.1之后&#xff0c;项目设置里的input选项&#xff0c;默认会有一条警告&#xff0c;告知旧的input系统已经不能用了。 做法 在content文件夹下新建一个input按钮 input文件夹里面分成两部分内容 1.…

【ARMv8 SIMD和浮点指令编程】浮点加减乘除指令——四则运算

浮点指令有专门的加减乘除四则运算指令,比如 FADD、FSUB、FMUL、FDIV 等。 1 FADD (scalar) 浮点加法(标量)。该指令将两个源 SIMD&FP 寄存器的浮点值相加,并将结果写入目标 SIMD&FP 寄存器。 该指令可以产生浮点异常。根据 FPCR 中的设置,异常会导致在 FPSR 中…

Ansible的role

环境 控制节点&#xff1a;Ubuntu 22.04Ansible 2.10.8管理节点&#xff1a;CentOS 8 role 目录结构 role的文件结构中&#xff0c;包含了8个标准目录&#xff1a; taskshandlerstemplatesfilesvarsdefaultsmetalibrary 例如&#xff0c;下面是 common 这个role的目录结构…

抖音小店从0到1起店流程,实操经验分享!

我是电商珠珠 很多人在开店之后&#xff0c;并不知道怎么做。往往会有人跑来问我说&#xff0c;开店之后怎么做啊&#xff0c;流程方面我还不是很熟悉啊等等。 这份起店流程备好了&#xff0c;将来对你有用。 第一步&#xff0c;店铺基础设置 在店铺开好之后&#xff0c;不…

Python图像处理之OpenCV模块

Python图像处理 1、OpenCV模块简介2、OpenCV模块图像常用操作3、PIL与OpenCV图像格式转换4、图像识别应用案例4.1、人脸识别4.2、车牌识别4.3、文本识别1、OpenCV模块简介 OpenCV(Open Source Computer Vision Library)是一个基于BSD许可(开源)发行的跨平台计算机视觉库,主…

Pytest系列(16)- 分布式测试插件之pytest-xdist的详细使用

前言 平常我们功能测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟&#xff0c;如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时&#xff0c;会需要协调多个测试资源来把任务分成两部分&#xff0c;于是执行时间缩短一半&#…

AVL树性质和实现

AVL树 AVL是两名俄罗斯数学家的名字&#xff0c;以此纪念 与二叉搜索树的区别 AVL树在二叉搜索树的基础上增加了新的限制&#xff1a;需要时刻保证每个树中每个结点的左右子树高度之差的绝对值不超过1 因此&#xff0c;当向树中插入新结点后&#xff0c;即可降低树的高度&…

Leetcode2909. 元素和最小的山形三元组 II

Every day a Leetcode 题目来源&#xff1a;2909. 元素和最小的山形三元组 II 解法1&#xff1a;枚举 前后缀分解 定义 preMin[i] 为前缀最小值&#xff0c;初始化 preMin[0] nums[0]&#xff0c;递推公式&#xff1a;preMin[i] min(preMin[i - 1], nums[i])。 定义 suf…

InSAR 滤波算法

目录 1.InSAR 滤波原理 2.InSAR 滤波算法 2.1 均值滤波 2.2 Goldstein 滤波 2.3 改进的Goldstein 滤波 2.4 精致 Lee 滤波 2.5 小波滤波2.6 NL-InSAR 滤波 2.7 InSAR-BM3D 滤波 3.参考文献 本文由CSDN点云侠原创&#xff0c;爬虫网站请自重。 InSAR 滤波是InSAR 技术处理中的一…

rviz添加qt插件

一、增加rviz plugin插件 资料&#xff1a;http://admin.guyuehome.com/42336 https://blog.51cto.com/u_13625033/6126970 这部分代码只是将上面两个链接中的代码整合在了一起&#xff0c;整合在一起后可以更好的理解其中的关系 1、创建软件包 catkin_create_pkg rviz_tel…

【MySQL】查询语句

文章目录 选择语句 / 子句比较运算符AND&#xff0c;OR&#xff0c;NOT运算符IN运算符BETWEEN运算符LIKE运算符REGEXP运算符 选择语句 / 子句 USE&#xff1a;选择使用的databaseSELECT&#xff1a;选择查询的列FROM&#xff1a;选择查询的表WHERE&#xff1a;条件查询ORDER B…

IntelliJ IDEA 如何修改默认Maven仓库地址

在使用idea过程中&#xff0c;每次新建项目或者打开项目时&#xff0c;maven仓库地址都会变为默认地址。如何修改默认地址&#xff0c;让其保持不变&#xff0c;如下这种方式可以简单快捷的设置。 1.打开idea&#xff0c;取消项目自动加载 2.点击 Customize,然后再点击 All se…

DeepLearning - 余弦退火热重启学习率 CosineAnnealingWarmRestartsLR

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134249925 CosineAnnealingWarmRestartsLR&#xff0c;即 余弦退火热重启学习率&#xff0c;周期性修改学习率的下降和上升&#xff0c;间隔幅度逐…