数据结构:打造高效的通讯录项目

 ✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:http://t.csdnimg.cn/oHJAK(数据结构与算法)

小新的主页:编程版小新-CSDN博客

今天就和小新一起来实现超级有意思的通讯录项目吧。通讯录其实就是顺序表,对通讯录的实现其实就是对顺序表的实现,只是我们又给顺序表起了一个新的名字叫通讯录。这一点一定要记住,不然在下面实现代码的时候就很容易晕头转向。

在上一篇文章中我们实现的顺序表中存放的是整型数据,现在我们要实现通讯录,根本不同就是存放的数据不同,要实现通讯录,我们存放的是结构体,结构体里包含了联系人的信息。

顺序表(通讯录)的实现是基于结构体,指针,动态内存开辟的,如果不是很理解的话,可以先收藏。http://t.csdnimg.cn/Oytke (这个是C语言的专栏,有需要的话可以看一下)

1.顺序表 

我们先看顺序表的实现:

SeqList.c:

#include"SeqList.h"
//顺序表的初始化
void SLInit(SL* ps)//传址调用
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr != NULL)//ps->arr{free(ps->arr);}ps->arr = NULL;//避免访问野指针ps->size = ps->capacity = 0;
}//检查是否用足够的空间
void SLCheck(SL* ps)
{if (ps->size == ps->capacity)//空间不够{//申请空间//三目操作符int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//少了等号。一个是赋值SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));//需要申请多大的空间if (tmp == NULL){perror("realloc fail");return;}//申请成功ps->arr = tmp;ps->capacity = newcapacity;}}//打印顺序表
void SLPrint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ", ps.arr[i]);}printf("\n");
}//顺序表的尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有空间SLCheck(ps);//插入ps->arr[ps->size++] = x;//细节之后置++
}//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有足够的空间SLCheck(ps);//先让顺序表中已有的数据整体往后移动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;//不要忘记++
}//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入之前要检查空间够不够SLCheck(ps);//先让pos及其之后的数据整体往后挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//ps->arr[pos+1]=ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}//删除指定位置的数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//让pos之后的数据整体往前挪动一位for (int i = pos; i< ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}
//顺序表的尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//顺序表不能为空--ps->size;
}//顺序表的头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//整体往前挪动一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//修改指定位置的数据
void SeqListModify(SL* ps, int pos, SLDataType x)
{assert(ps);  //断言assert(ps->size > 0);  //顺序表不能为空assert(pos >= 0 && pos < ps->size);  //检查pos下标的合法性ps->arr[pos] = x;  //修改pos下标处对应的数据
}//查找指定数据
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){//找到了return i;//返回下标}}//没有找到return -1;}

SeqList.h:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//定义顺序表//静态顺序表
//#define N 100
//
//struct SeqList
//{
//	int arr[N];
//	int size;//有效数据个数
//};//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据个数int capacity;//空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDestroy(SL* ps);//尾部插入
void SLPushBack(SL* ps, SLDataType x);//尾部删除
void SLPopBack(SL* ps);//头部插入
void SLPushFront(SL* ps, SLDataType x);//头部删除
void SLPopFront(SL* ps);//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);//指定位置删除
void SLErase(SL* ps, int pos);//打印顺序表
void SLPrint(SL ps);//查找数据
int SLFind(SL* ps, SLDataType x);//修改指定位置的数据
void SeqListModify(SL* ps, int pos, SLDataType x);

如果不能理解的话: 数据结构:去发现顺序表的魅力所在-CSDN博客

既然通讯录就是顺序表,我们要实现通讯录就是基于在顺序表的基础上去扩展的。

2.通讯录的功能

1.通讯录的声明

2.通讯录的初始化

3.添加联系人

4.删除联系人

5.查找联系人

6.修改联系人

7.展示通讯录

8.销毁通讯录

3.通讯录的功能实现

一定要理解对通讯录的实现就是对顺序表的实现,在顺序表中实现的功能,下面我们会直接调用使用。

3.1通讯录的声明

#pragma once//防止重复引入产生问题
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100//定义联系人数据 结构
//姓名 性别  年龄  电话  地址typedef struct personInfo//方便书写,给结构体起一个简单的名字peoInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}peoInfo;

3.2通讯录的初始化

对通讯录的实现其实就是就是对顺序表的实现
通讯录就是顺序表,只是又给顺序表起了一个新的名字叫通讯录

实现通讯录要用到顺序表的方法,下面就给顺序表起一个新的名字叫通讯录Contact

typedef struct SeqList Contact;
//通讯录的初始化
void ContactInit(Contact* con)
{//对通讯录的初始化其实就是对顺序表的初始化//顺序表的初始化前面已经实现好了,直接调用就好了SLInit(con);
}

3.3添加联系人数据

//通讯录添加数据
void ContactAdd(Contact* con)
{//获取用户的内容:姓名+性别+年龄+电话+住址peoInfo info;printf("请输入要添加的联系人的姓名\n");scanf("%s", info.name);printf("请输入要添加的联系人的性别\n");scanf("%s", info.gender);printf("请输入要添加的联系人的年龄\n");scanf("%d", &info.age);printf("请输入要添加的联系人的电话\n");scanf("%s", info.tel);printf("请输入要添加的联系人的住址\n");scanf("%s", info.addr);//往通讯录里添加用户即联系人的信息//这里采用尾插SLPushBack(con, info);
}

3.4查找联系人 

//通讯录的查找
void ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");scanf("%s", name);int find = FindName(con,name);if (find < 0){printf("没有该联系人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%3s %3s %3d %3s %3s\n",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);//这里根据需要修改格式}
}

3.5删除联系人数据

//查找联系人姓名
int FindName(Contact* con ,char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(con->arr[i].name, name)){//找到了return i;}}//没有找到return -1;
}
//通讯录删除数据
void ContactDel(Contact* con)
{//要删除的数据必须存在//查找要删除的联系人//这里我们按名字进行查找char name[NAME_MAX];printf("请输入要删除的联系人姓名\n");scanf("%s", name);int find = FindName(con, name);if (find < 0){printf("要删除的联系人信息不存在\n");}//要删除的联系人信息存在SLErase(con, find);printf("删除成功\n");}

3.6修改联系人信息

//修改联系人信息
void ContactModity(Contact* con)
{//要修改的联系人数据存在printf("请输入要修改的联系人姓名\n");char name[NAME_MAX];scanf("%s", name);int find = FindName(con, name);if (find < 0){printf("要修改的联系人信息不存在\n");return;}//直接修改printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d",&con->arr[find].age);printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功\n");
}

3.7展示通讯录

//展示通讯录
void ContactShow(Contact* con)
{//打印表头printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");//遍历通讯录,打印通讯录的联系人信息for (int i = 0; i < con->size; i++){printf("%3s %3s %3d %3s %3s\n",con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);//这里根据需要修改位置,让打印的更加美观}}

3.9销毁通讯录

//通讯录的销毁
void ContactDestroy(Contact* con)
{SLDestroy(con);
}

4.整体代码

Contact.h:

#pragma once//防止重复引入问题
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100//定义联系人数据 结构
//姓名 性别  年龄  电话  地址typedef struct personInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}peoInfo;//对通讯录的实现其实就是就是对顺序表的实现
//通讯录就是顺序表,只是又给顺序表起了一个新的名字叫通讯录//实现通讯录要用到顺序表的方法,下面就给顺序表起一个新的名字叫通讯录
typedef struct SeqList Contact;//通讯录的相关方法//通讯录的初始化
void ContactInit(Contact* con);//通讯录的销毁
//void ContactDestroy(Contact* con);//通讯录添加数据
void ContactAdd(Contact* con);//通讯录删除数据
void ContactDel(Contact* con);//通讯录的修改
void ContactModity(Contact* con);//展现通讯录
void ContactShow(Contact* con);//查找通讯录
void ContactFind(Contact* con);

Contact.c:

#include"SeqList.h"
#include"Contact.h"
//通讯录的初始化
void ContactInit(Contact* con)
{//对通讯录的初始化其实就是对顺序表的初始化//顺序表的初始化前面已经实现好了,直接调用就好了SLInit(con);
}//通讯录的销毁
void ContactDestroy(Contact* con)
{SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{//获取用户的内容:姓名+性别+年龄+电话+住址peoInfo info;printf("请输入要添加的联系人的姓名\n");scanf("%s", info.name);printf("请输入要添加的联系人的性别\n");scanf("%s", info.gender);printf("请输入要添加的联系人的年龄\n");scanf("%d", &info.age);printf("请输入要添加的联系人的电话\n");scanf("%s", info.tel);printf("请输入要添加的联系人的住址\n");scanf("%s", info.addr);//往通讯录里添加用户即联系人的信息//这里采用尾插SLPushBack(con, info);
}//查找联系人
int FindName(Contact* con ,char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(con->arr[i].name, name)){//找到了return i;}}//没有找到return -1;
}//通讯录删除数据
void ContactDel(Contact* con)
{//要删除的数据必须存在//查找要删除的联系人//这里按名字进行查找char name[NAME_MAX];printf("请输入要删除的联系人姓名\n");scanf("%s", name);int find = FindName(con, name);if (find < 0){printf("要删除的联系人信息不存在\n");}//要删除的联系人信息存在SLErase(con, find);printf("删除成功\n");}
//修改联系人信息
void ContactModity(Contact* con)
{//要修改的联系人数据存在printf("请输入要修改的联系人姓名\n");char name[NAME_MAX];scanf("%s", name);int find = FindName(con, name);if (find < 0){printf("要修改的联系人信息不存在\n");return;}//直接修改printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d",&con->arr[find].age);//scanf传入咋用的,好好想想,看下之前的例子,这个得好好记住了,再检查下printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功\n");
}//展示通讯录
void ContactShow(Contact* con)
{//打印表头printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");//遍历通讯录,打印通讯录的联系人信息for (int i = 0; i < con->size; i++){printf("%3s %3s %3d %3s %3s\n",con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}}//通讯录的查找
void ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");scanf("%s", name);int find = FindName(con,name);if (find < 0){printf("没有该联系人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%3s %3s %3d %3s %3s\n",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);}
}

SeqList.h:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"
//定义数据结构//静态数据结构
//#define N 100
//
//struct SeqList
//{
//	int arr[N];
//	int size;//有效数据个数
//};//动态数据结构
typedef peoInfo SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据个数int capacity;//空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDestroy(SL* ps);//尾部插入
void SLPushBack(SL* ps, SLDataType x);//尾部删除
void SLPopBack(SL* ps);//头部插入
void SLPushFront(SL* ps, SLDataType x);//头部删除
void SLPopFront(SL* ps);//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);//指定位置删除
void SLErase(SL* ps, int pos);

SeqList.c:

#include"SeqList.h"
//顺序表的初始化
void SLInit(SL* ps)//传址调用
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr != NULL)//ps->arr{free(ps->arr);}ps->arr = NULL;//避免访问野指针ps->size = ps->capacity = 0;
}//检查是否用足够的空间
void SLCheck(SL* ps)
{if (ps->size == ps->capacity)//空间不够{//申请空间//三目操作符int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));//需要申请多大的空间if (tmp == NULL){perror("realloc fail");return;}//申请成功ps->arr = tmp;ps->capacity = newcapacity;}}//顺序表的尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有空间SLCheck(ps);//插入ps->arr[ps->size++] = x;//细节之后置++
}//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有足够的空间SLCheck(ps);//先让顺序表中已有的数据整体往后移动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;//不要忘记++
}//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入之前要检查空间够不够SLCheck(ps);//先让pos及其之后的数据整体往后挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//ps->arr[pos+1]=ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}//删除指定位置的数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//让pos之后的数据整体往前挪动一位for (int i = pos; i< ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}
//顺序表的尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//顺序表不能为空--ps->size;
}//顺序表的头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//整体往前挪动一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

text.c:

#include"SeqList.h"
#include"Contact.h"通讯录的测试方法
//void SLTest01()
//{
//	Contact con;//创建通讯录对象其实实际上就是顺序表对象 等同于SL sl
//	SLInit(&con);
//	ContactAdd(&con);
//	ContactAdd(&con);
//	ContactShow(&con);
//
//
//}//大家在实现通讯录的功能的时候,可以写完一个功能就去测试一个功能,避免堆在一起难找到错误void menu()
{printf("****************通讯录****************\n");printf("******1.增加联系人  2.删除联系人******\n");printf("******3.修改联系人  4.查找联系人******\n");printf("******5.展示联系人  0.  退出   *******\n");printf("**************************************\n");
}int main()
{int op = 0;Contact con;ContactInit(&con);do{menu();printf("请选择菜单:");scanf("%d", &op);switch (op){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactModity(&con);break;case 4:ContactFind(&con);break;case 5:ContactShow(&con);break;case 0:printf("退出通讯录...\n");break;default:printf("输出错误,请重新选择你的操作\n");break;}} while (op != 0);//SLTest01();ContactDestroy(&con);return 0;
}

下课了~

下次别忘了来哦

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

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

相关文章

python爬虫原理和编程实战:爬取CSDN博主的账号信息

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

【重磅开源】一款可以生成SpringBoot+Vue代码的轻量级项目

基于SpringBootVue3开发的轻量级快速开发脚手架 &#x1f341;项目简介 一款通用的前、后端项目模板 一款快速开发管理系统的项目 一款可以生成SpringBootVue代码的项目 一款持续迭代的开源项目 一个程序员的心血合集 度过严寒&#xff0c;终有春日&#xff…

JavaSE图书管理系统实战

代码仓库地址&#xff1a;Java图书管理系统 1.前言 该项目将JavaSE的封装继承多态三大特性&#xff0c;使用了大量面向对象的操作&#xff0c;有利于巩固理解 &#xff08;1&#xff09;实现效果 2.实现步骤 第一步先把框架搭建起来&#xff0c;即创建出人&#xff1a;管理员和…

将图片按灰度转换成字符

from struct import *ch [., :, !, ~, ,, ^, *,$, #] ch.reverse()def calc(R, G, B):#模式Lreturn R * 299 // 1000 G * 587 // 1000 B * 144 / 1000def character( val):num val / 260 * len(ch)num round(num)if num>len(ch):numlen(ch)-1return ch[num]class rmb:d…

IIC总线读取温度湿度传感器数据实验

iic.c #include "iic.h"extern void printf(const char* fmt, ...); /** 函数名 &#xff1a; delay_us* 函数功能&#xff1a;延时函数* 函数参数&#xff1a;无* 函数返回值&#xff1a;无* */ void delay_us(void) //微秒级延时 {unsigned int i 2000;while(i-…

CNN卷积神经网络:理论基础、核心架构与多元应用

CNN是一种深度学习模型&#xff0c;利用卷积层提取图像特征&#xff0c;池化层降维与增强不变性&#xff0c;全连接层实现分类/回归。核心理论包括局部感知、权值共享、多层抽象。广泛应用图像识别、目标检测、语义分割、生成任务等领域。 一、CNN理论基础 1、局部感知野&…

【迅为iMX6Q】开发板 Linux version 6.6.3 SD卡 启动

开发环境 win10 64位 VMware Workstation Pro 16 ubuntu 20.04 【迅为imx6q】开发板&#xff0c; 2G DDR RAM linux-imx 下载 使用 NXP 官方提供的 linux-imx&#xff0c;代码地址为&#xff1a; https://github.com/nxp-imx/linux-imx 使用 git 下载 linux-imx&#xff…

Dual-AMN论文阅读

Boosting the Speed of Entity Alignment 10: Dual Attention Matching Network with Normalized Hard Sample Mining 将实体对齐速度提高 10 倍&#xff1a;具有归一化硬样本挖掘的双重注意力匹配网络 ABSTRACT 寻找多源知识图谱(KG)中的等效实体是知识图谱集成的关键步骤&…

IoC与Spring

目录 IoC控制反转 现实案例 特点 目的 DI依赖注入 小总结 介绍Spring 狭义和广义上的Spring 传统编码方式的不足 需求引入 弊端分析 IoC控制反转 现实案例 1、买水果问老板各种水果的口感而不是自己去挨个尝试一遍。 2、买房子找中介而不是自己去花时间找房东。…

springcloud 整合swagger文档教程

我用的是nacos和gateway 我的模块 父依赖没什么太大关系如果出现版本冲突问题可用参考我的依赖版本 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org…

claude国内无法使用的解决办法

claude3国内如何使用, claude国内无法使用的解决办法来啦&#xff01; 近日&#xff0c;人工智能公司AnthropicAI推出了全新的大语言模型Claude 3系列&#xff0c;其中最强大的版本Claude 3 Opus据称在性能上全面超越了OpenAI的GPT-4模型。Claude 3系列包括三个版本&#xff1…

金融科技领航者 财源滚滚选股软件助力投资者智赢未来

在波澜壮阔的金融科技浪潮中&#xff0c;河北源达凭借深厚的行业积淀与前瞻的创新思维&#xff0c;逐渐崭露头角&#xff0c;成为业界瞩目的领航者。多年来&#xff0c;公司始终坚守初心&#xff0c;致力于为客户提供高效、的金融科技服务&#xff0c;助力投资者在资本市场中稳…