当前位置: 首页 > news >正文

顺序表的应用

顺序表的应用

前情回顾

在这里插入图片描述

在指定位置插入数据

在这里插入图片描述

代码如下:

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//pos=ps->size相当于尾插//插入数据看空间大小够不够SLCheckCapacity(ps);//让pos及之后的数据的数据往后挪动一位for (int i =ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

在指定位置删除数据

在这里插入图片描述

特别注意

assert(ps >= 0 && pos < ps->size);

这里pos不可以等于ps->size,因为size是有效个数的下一位,删去一位之后位置就空了一位,就没有意义

代码如下:

void SLErase(SL* ps, int pos)
{assert(ps);assert(ps >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i--){ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]}ps->size--;
}

查找数据

//查找
void SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到了if (ps->arr[i] == x){return i;}}//找不到return -1;//返回不存在的下标,-2,-3都可以
}

基于顺序表实现通讯录项目

在这里插入图片描述

这个代表有个联系人

在这里插入图片描述

这个是联系人里面所要存储的信息

在这里插入图片描述

写通讯录就相当于写一个结构体的顺序表

详情如下:

在这里插入图片描述

顺序表里面可以存放内置的数据:int, char,也可以是自定义类型如结构体

接下来是一个大体的框架:

在这里插入图片描述

为什么在SeqList.h里面typedef peoInfo SLDataType 不要加上struct呢?

根据前面学过的预处理相关的知识可以知道,我们这里包含了Contact.h这个头文件,就相当于Contact.h文件里面全部内容在SeqList.h里面,所以不用加struct

下图为模型:

在这里插入图片描述

小小补充:

关于scanf函数:

scanf("",);//双引号后面是变量的地址

如下:

int a;
scanf("%d",&a);

再看这个:

char name[10];
scanf("%s",name);//数组名就是sh

最终想要实现的形式:
在这里插入图片描述

代码过程如下:

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 ContactDestory(Contact* con);//通讯录添加数据void ContactAdd(Contact* con);//通讯录删除void ContactDel(Contact* con);//通讯录的修改void ContactModify(Contact* con);//通讯录的查找void ContactFind(Contact* con);//通讯录的展示void ContactShow(Contact* con);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
#include "SeqList.h"
void LoadContact(Contact* con) {FILE* pf = fopen("contact.txt", "rb");if (pf == NULL) {perror("fopen error!\n");return;}//循环读取⽂件数据peoInfo info;while (fread(&info, sizeof(peoInfo), 1, pf)){SeqListPushBack(con, info);}printf("历史数据导⼊通讯录成功!\n");
}
//通讯录的初始化
void ContactInit(Contact* con)
{//实际上要进行的顺序表的初始化//顺序表的初始化已经实现好了SLInit(con);LoadContact(con);
}
//通讯录的销毁
void ContactDestory(Contact* con)
{SLDestory(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 FindByName(Contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(con->arr[i].name, name)){return i;//找到了}else{return -1;//没找到,返回一个无效指令}}
}
//通讯录的删除
void ContactDel(Contact* con)
{//要删除的数据必须要存在,才能被执行删除操作//查找char name[NAME_MAX];printf("请输入要删除的联系人的姓名:\n");scanf("%s",name);int Find = FindByName(con, name);if (Find < 0){printf("要删除的联系人数据不存在\n");return;}//要删除的联系人的数据存在--->知道了要删除的联系人数据对应的下标SLErase(con, name);printf("删除成功");
}
//通讯录的展示
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 ContactModify(Contact* con)
{//要修改的联系人信息存在char name[NAME_MAX];printf("请输入要修改的联系人的姓名:\n");scanf("%s", name);int Find = FindByName(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");
}
//通讯录的查找
void ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人的姓名:\n");scanf("%s", name);int Find = FindByName(con, name);if (Find < 0){printf("要查找的联系人数据不存在\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");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 SaveContact(	Contact* con) {FILE* pf = fopen("contact.txt", "wb");if (pf == NULL) {perror("fopen error!\n");return;}//将通讯录数据写⼊⽂件for (int i = 0; i < con->size; i++){fwrite(con->size, sizeof(peoInfo), 1, pf);}printf("通讯录数据保存成功!\n");
}

SeqList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
//一般不推荐写静态顺序表
//以下是动态顺序表
typedef peoInfo SLDataType;
struct SeqList
{SLDataType* arr;int size;//有效的数据大小int capacity;//空间大小
}SL;
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//顺序表的打印
void SLPrint(SL s);
//头部插入删除 / 尾部插入删除
//插入
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
//删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
void SLFind(SL* ps, SLDataType x);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//专门封装一个函数用来检查空间是否够不够
void SLCheckCapacity(SL* ps)
{//插入前先看空间够不够if (ps->capacity == ps->size){//温柔的解决方法if (ps == NULL){return;}//判断空间大小是否为0// 三目表达式int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//申请空间SLDataType* tmp = realloc(ps->arr, ps->newCapacity * 2 * sizeof(SLDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}//空间申请成功ps->arr = tmp;ps->capacity = newCapacity;}
}
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capcacity = 0;
}
void SLDestory(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capcacity = 0;
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//ps->arr[ps->size]=x;//++ps->size;ps->arr[ps->size++] = x;//这行代码是将上面的两行代码变成了一行代码,//对其size进行了后置++,提高程序运行效率
}
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//先让顺序表已有的数据往后挪动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];//arr[1]=arr[0],最后一次情况是这样,由此来推断i的限制条件ps->size++;//特别要注意了}ps->arr = x;
}//void SLPrint(SL s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}
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 < size - 2; i++){ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1];}ps->size--;
}
//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//pos=ps->size相当于尾插//插入数据看空间大小够不够SLCheckCapacity(ps);//让pos及之后的数据的数据往后挪动一位for (int i =ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(ps >= 0 && pos < ps->size);SLCheckCapacity(ps);for (int i = pos; i < ps->size - 1; i--){ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]}ps->size--;
}
//查找
//void SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		//找到了
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	//找不到
//	return -1;//返回不存在的下标,-2,-3都可以
//}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//int main()
//void SLTest01()
//{
//	SL sl;
//	SLInit(&sl);
//	//增删查改操作
//	//测试尾插
//	SLPushBack(&sl, 1);
//	SLPushBack(&sl, 2);
//	SLPushBack(&sl, 3);
//	SLPushBack(&sl, 4);
//	//SLPushBack(NULL, 5);
//	SLPrint(sl);
//	SLPushFront(&sl, 6);
//	SLPrint(sl);
//	SLDestory(&sl);
//}
//void SLTest02()
//{
//	SLInsert(&sl, 0, 99);
//	SLErase(&sl, 0);
//	SLPrint(sl);
//	int find = SLFind(&sl, 4);
//	if (find < 0)
//	{
//		printf("没有找到");
//	}
//	else
//	{
//		printf("找到了,下标为%d\n", find);
//	}
//}
//void ContactTest01()
//{
//	Contact con;//创建的通讯录对象 实际上就是 顺序表对象 等价于SL sl
//	ContactInit(&con);
//	ContactAdd(&con);
//	ContactShow(&con);
//	ContactModify(&con);
//	ContactFind(&con);
//	ContactDel(&con);
//	ContactShow(&con);
//	ContactDestory(&con);
//}
void menu()
{printf("*************************\n");printf("*******1.添加2.删除******\n");printf("*******3.修改4.查找******\n");printf("*******5.查找0.退出******\n");
}
int main()
{//SLTest01();//ContactTest01();int op = -1;Contact con;ContactInit(&con);do{menu();printf("请选择您的操作:\n");scanf("%d", &op);//要根据对应的op执行对应的操作switch (op){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactModify(&con);break;case 4:ContactFind(&con);break;case 5:ContactShow(&con);break;case 0:printf("退出通讯录\n");default:break;}} while (op!=0);ContactDestory(&con);return 0;
}

***\n");
printf(“*5.查找0.退出\n”);
}
int main()
{
//SLTest01();
//ContactTest01();
int op = -1;
Contact con;
ContactInit(&con);
do
{
menu();
printf(“请选择您的操作:\n”);
scanf(“%d”, &op);
//要根据对应的op执行对应的操作
switch (op)
{
case 1:
ContactAdd(&con);
break;
case 2:
ContactDel(&con);
break;
case 3:
ContactModify(&con);
break;
case 4:
ContactFind(&con);
break;
case 5:
ContactShow(&con);
break;
case 0:
printf(“退出通讯录\n”);
default:
break;
}
} while (op!=0);
ContactDestory(&con);
return 0;
}


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • unity对于文件夹的操作
  • 大数据面试题之Flink(1)
  • 如何网页在线编辑微软Office Word,并导出为PDF格式。
  • APP渗透-android12夜神模拟器+Burpsuite实现
  • uni-app上传失败超出文件限制解决方法-分包处理-预加载
  • Android --- 新电脑安装Android Studio 使用 Android 内置模拟器电脑直接卡死,鼠标和键盘都操作不了
  • AI绘画Stable Diffusion【图生图教程】:图片高清修复的三种方案详解,你一定能用上!(附资料)
  • MSPM0G3507——解决printf重定向在其他位置不能用的问题(printf重定向的补充)
  • 【密码学】密码学五要素
  • 使用c++进行大规模的矩阵运算
  • Debezium日常分享系列之:Debezium 2.7.0.Final发布
  • Qt使用sqlite数据库及项目实战
  • 微信小程序利用第三方库xlsx导出excel
  • Docker-基础
  • LeetCode 30. 串联所有单词的子串
  • IndexedDB
  • javascript从右向左截取指定位数字符的3种方法
  • JS基础之数据类型、对象、原型、原型链、继承
  • Meteor的表单提交:Form
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 爱情 北京女病人
  • 力扣(LeetCode)56
  • 前端性能优化——回流与重绘
  • 前端知识点整理(待续)
  • 如何选择开源的机器学习框架?
  • 微信小程序实战练习(仿五洲到家微信版)
  • ​​​​​​​​​​​​​​Γ函数
  • # Panda3d 碰撞检测系统介绍
  • # 消息中间件 RocketMQ 高级功能和源码分析(七)
  • #数据结构 笔记三
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (转)EOS中账户、钱包和密钥的关系
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET Remoting学习笔记(三)信道
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET8使用VS2022打包Docker镜像
  • .NET关于 跳过SSL中遇到的问题
  • .NET值类型变量“活”在哪?
  • .sdf和.msp文件读取
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • :O)修改linux硬件时间
  • @EnableAsync和@Async开始异步任务支持
  • @ResponseBody
  • @Responsebody与@RequestBody
  • [2669]2-2 Time类的定义
  • [Django开源学习 1]django-vue-admin
  • [ffmpeg] av_opt_set 解析
  • [HTML]Web前端开发技术18(HTML5、CSS3、JavaScript )HTML5 基础与CSS3 应用——喵喵画网页
  • [iOS]如何删除工程里面用cocoapods导入的第三方库