【数据结构|C语言版】单链表应用

  • 前言
  • 1. 基于单链表实现通讯录
    • 1.1 知识要求
    • 1.2 功能要求
  • 2. 代码总结
    • 2.1 SeqList.h
    • 2.2 SeqList.c
    • 2.3 Contact.h
    • 2.4 Contact.c
    • 2.5 test.c
  • 后言


在这里插入图片描述

上期回顾:【数据结构|C语言版】单链表

前言

各位小伙伴大家好!上期小编讲解了单链表相关知识,在此基础上,我们来学习一下单链表的应用。
在这里插入图片描述

1. 基于单链表实现通讯录

1.1 知识要求

C语言基础要求:结构体、动态内存管理、单链表、文件操作

1.2 功能要求

① 至少能够存储100个人的通讯信息
② 能够保存用户信息:名字、性别、年龄、电话、地址等
③ 增加联系人信息
④ 删除指定联系人
⑤ 查找制定联系人
⑥修改指定联系人
⑦ 显示联系人信息

2. 代码总结

2.1 SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"//定义链表的结构
//typedef int SLDataType
typedef struct ContactInfo SLDataType;   //更改SLDataType的类型typedef struct SListNode
{SLDataType data;	//保存的数据struct SListNode* next;		//指针变量存放下一个节点的地址
}SLNode;//1 打印链表
void SLPrint(SLNode* phead);//2 尾插
void SLPushBack(SLNode** pphead, SLDataType x);
//3 头插
void SLPushFront(SLNode** pphead, SLDataType x);//4 尾删
void SLPopBack(SLNode** pphead);//5 头删
void SLPopFront(SLNode** pphead);//SLFind()找到要查找数据的下标
//找节点的函数这里传一级实际上就可以了,因为不改变头结点
//但是这里要写二级指针,因为要保持接口一致性
//缺点:这个函数有一定的局限性,他找到数据x的下标是第一次出现的x的下标后,不会找后续的x的下标
SLNode* SLFind(SLNode** pphead, SLDataType x);//6 定点前插入数据
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x);//7 定点后插入数据
void SLInsertAfter(SLNode* pos, SLDataType x);//8 删除pos节点
void  SLErase(SLNode** pphead, SLNode* pos);//9 删除pos后的节点
void SLEraseAfter(SLNode* pos);//10 销毁链表
void SLDestory(SLNode** pphead);

2.2 SeqList.c

#include"SList_copy.h"//1 创建新的节点的函数
SLNode* SLBuyNode(SLDataType x)
{SLNode* node = (SLNode*)malloc(sizeof(SLNode));node->data = x;node->next = NULL;return node;
}//2 尾插
void SLPushBack(SLNode** pphead, SLDataType x)	//保存第一个节点的指针的地址
{assert(pphead);//创建一个节点SLNode* node = SLBuyNode(x);if (*pphead == NULL){*pphead = node;return;}//链表不为空,找尾SLNode* pcur = *pphead;while (pcur->next)//相当于pcur->next!=NULL{pcur = pcur->next;}pcur->next = node;
}//3 头插
void SLPushFront(SLNode** pphead, SLDataType x)
{assert(pphead);SLNode* node = SLBuyNode(x);//新结点跟头结点连接起来node->next = *pphead;//让新节点成为头结点*pphead = node;
}//4 尾删
void SLPopBack(SLNode** pphead)
{assert(pphead);assert(*pphead);	//第一个节点不能为空//判断只有一个结点的情况if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}//找到尾节点和尾节点的前一个节点SLNode* pre = NULL;SLNode* ptail = *pphead;while (ptail->next){pre = ptail;ptail = ptail->next;}//pre的next指针不指向ptail,而是指向ptail的下一个节点//pre->next = NULL;pre->next = ptail->next;//因为在SLPrint(SLNode* phead)函数中有判断节点是否为空while (pcur),所以置空free(ptail);ptail = NULL;}//5 头插
void SLPopFront(SLNode** pphead)
{assert(pphead);assert(*pphead);	//第一个节点不能为空SLNode* del = *pphead;*pphead = (*pphead)->next;free(del);del = NULL;
}//6 定点前插入数据
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x)
{assert(pphead);assert(pos);	//pos不能为空assert(*pphead);  //NULL前插入数据是荒谬的,所以assert第一个节点SLNode* node = SLBuyNode(x);//当只有一个结点(pos就是第一个节点)//if (((*pphead)->next) == NULL||pos==*pphead),可以简化成以下代码if (pos == *pphead) {node->next = *pphead;*pphead = node;return;}//找到pos的前一个节点SLNode* pre = *pphead;while (pre->next != pos){pre = pre->next;}//处理pre node pos的位置node->next = pos;pre->next = node;
}//7 定点后插入数据
void SLInsertAfter(SLNode* pos, SLDataType x)
{assert(pos);SLNode* node = SLBuyNode(x);node->next = pos->next;pos->next = node;
}//8 删除pos节点
void SLErase(SLNode** pphead, SLNode* pos)
{assert(*pphead);assert(pphead);assert(pos);//pos是头结点if (pos == *pphead){*pphead = (*pphead)->next;free(pos);return;}//pos不是头结点,找pos的前一个节点SLNode* pre = *pphead;while (pre->next != pos){pre = pre->next;}pre->next = pos->next;free(pos);pos = NULL;   //代码规范
}//9 删除pos后的节点
void SLEraseAfter(SLNode* pos)
{//删除pos之后的节点也不能空assert(pos && pos->next);SLNode* del = pos->next;pos->next = del->next;free(del);
}void SLDestory(SLNode** pphead)
{assert(pphead);SLNode* pcur = *pphead;while (pcur){SLNode* next = pcur->next;free(pcur);pcur = next;}//头结点记得置空*pphead = NULL;
}

2.3 Contact.h

#pragma once
//创建保存联系人数据的结构
#define NAME_MAX 120
#define SEX_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 50typedef struct ContactInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}ConInfo;
//前置声明
typedef struct SListNode contact;//1.打开通讯录
void ContactInit(contact** pcon);//2.保存数据后销毁通讯录
void ContactDestory(contact** pcon);//3.添加联系人
void ContactAdd(contact** pcon);//4.删除联系人
void ContactDel(contact** pcon);//5.修改联系人
void ContactModify(contact* con);//6.查找联系人
void ContactFind(contact* pcon);//7.查看通讯录
void ContactShow(contact* pcon);

2.4 Contact.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
#include"SList_copy.h"//1.打开通讯录
void ContactInit(contact** pcon)
{FILE* pf = fopen("Contact_Info.txt", "rb");if (pf == NULL){perror("fopen error.\n");  //主动报错,打开失败return;}ConInfo info;//回顾一下fread //size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );//从流中读取一个由count元素组成的数组,每个元素的大小为size字节,并将它们存储在ptr指定的内存块中。//流的位置指示器按读取的总字节数前进。//如果成功读取的总字节数为(size * count)while (fread(&info, sizeof(info), 1, pf)){SLPushBack(pcon, info);}printf("历史数据已导入通讯录\n");
}void ContactSave(contact* con)
{FILE* pf = fopen("Contact_Info.txt", "wb");if (pf == NULL){perror("fopen error\n");return;}contact* cur = con;while (cur){fwrite(&(cur->data), sizeof(cur->data), 1, pf);cur = cur->next;}printf("成功保存通讯录数据\n");
}void ContactDestory(contact** pcon)
{ContactSave(*pcon);SLDestory(pcon);
}void ContactAdd(contact** pcon)
{ConInfo 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(pcon, info);printf("已添加联系人数据\n");
}//我们这里通过姓名删除联系人
contact* FindByName(contact* con, char name[])
{contact* cur = con;while (cur){if (strcmp(cur->data.name,name) == 0){return cur;}cur = cur->next;}return NULL;
}void ContactDel(contact** pcon)
{char name[NAME_MAX];printf("请输入你要删除的联系人姓名:\n");scanf("%s", name);contact* pos = FindByName(*pcon, name);if (pos == NULL){printf("该联系人不存在\n");return;}SLErase(pcon, pos);printf("已删除该联系人\n");
}void ContactModify(contact* con)
{char name[NAME_MAX];printf("请输入你要修改的联系人姓名:\n");scanf("%s", name);contact* pos = FindByName(con, name);if (pos == NULL){printf("该联系人不存在\n");return 1;}printf("该联系人姓名修改为:\n");scanf("%s", pos->data.name);	printf("该联系人性别修改为:\n");scanf("%s", pos->data.sex);	printf("该联系人年龄修改为:\n");scanf("%d", &pos->data.age);	printf("该联系人电话修改为:\n");scanf("%s", pos->data.tel);printf("该联系人地址修改为:\n");scanf("%s", pos->data.addr);printf("修改成功\n");
}void ContactFind(contact* con)
{char name[NAME_MAX];printf("请输入你要查找的联系人姓名:\n");scanf("%s", name);contact* pos = FindByName(con, name);if (pos == NULL){printf("该联系人不存在\n");return;}printf("找到了\n");printf("%s %s %d %s %s\n",pos->data.name,pos->data.sex,pos->data.age,pos->data.tel,pos->data.addr);
}void ContactShow(contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");contact* cur = con;while (cur){printf("%s %s %d %s %s\n", cur->data.name, cur->data.sex, cur->data.age, cur->data.tel, cur->data.addr);cur = cur->next;}
}

2.5 test.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
#include"SList_copy.h"void test1()
{contact *pcontact=NULL;ContactInit(&pcontact);
}void test2()
{contact* pcontact = NULL;ContactInit(&pcontact);ContactAdd(&pcontact);ContactDel(&pcontact);ContactShow(pcontact);}void test3()
{contact* pcontact = NULL;ContactInit(&pcontact);ContactShow(pcontact);ContactAdd(&pcontact);ContactShow(pcontact);ContactDel(&pcontact);ContactShow(pcontact);
}
void test4()
{contact* pcontact = NULL;ContactInit(&pcontact);ContactAdd(&pcontact);ContactAdd(&pcontact);ContactShow(pcontact);ContactFind(pcontact);ContactShow(pcontact);}void test5()
{contact* pcontact = NULL;ContactInit(&pcontact);ContactAdd(&pcontact);ContactShow(pcontact);ContactModify(pcontact);ContactShow(pcontact);ContactDestory(&pcontact);
}void menu()
{printf("\n");printf("****************************\n");printf("****************************\n");printf("************通讯录***********\n");printf("*********1.添加联系人********\n");printf("*********2.删除联系人********\n");printf("*********3.修改联系人********\n");printf("*********4.查找联系人********\n");printf("*********5.查看通讯录********\n");printf("*********0.退  出************\n");printf("****************************\n");printf("****************************\n");
}int main()
{//test1();//test2();//test3();//test4();//test5();int op = 0;contact* con=NULL;ContactInit(&con);do {menu();printf("请选择:\n");scanf("%d", &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");break;default:printf("输入错误\n");break;}} while (op!=0);ContactDestory(&con);return 0;
}

后言

以上就是小编对单链表应用的一些初步认识。
如果觉得小编讲的还可以,还请一键三连。互三必回!
持续更新中!
在这里插入图片描述

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

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

相关文章

麒麟服务器操作系统安装HTTP服务

往期好文&#xff1a;麒麟服务器操作系统安装TFTP服务 Hello&#xff0c;大家好啊&#xff01;今天我们将探讨如何在麒麟服务器操作系统上安装和配置HTTP服务&#xff0c;这是任何网络服务或应用的基础。无论你是想建立一个简单的网站&#xff0c;还是需要一个全功能的Web服务器…

实景三维技术在公共安全领域的应用

随着科技的不断发展&#xff0c;实景三维技术在公共安全领域的应用越来越广泛。实景三维技术是指通过采集现实世界的三维数据&#xff0c;构建出真实的三维场景&#xff0c;进而实现对现实世界的数字化模拟和重建。在公共安全领域&#xff0c;实景三维技术的应用不仅可以提高安…

【MySQL】 mysql 日常工单处理脚本 解放你的双手!!!

简介 在工作中经常帮助开发的小伙伴执行些 sql&#xff0c;手动执行效率低不直观&#xff0c;还要单独备份等等&#xff0c;极为麻烦&#xff0c;怎么办&#xff1f;用它&#xff01;解放时间多摸鱼&#xff01;&#xff01;&#xff01;我的摸鱼小帮手。 流程图&#xff1a;…

PHP学习(二)

一、php 数据类型之查看和判断数据类型 查看数据类型 1.gettype(传入一个变量) 能够获得变量的类型 2.var_dump(传入一个变量) 输出变量类型和值 <?php //声明一个变量 88.8 $f 88.8; $type gettype($f); echo $type; ?> <?php //多换几个类型试试 $str 你…

MySQL 实例employee表综合查询

目录 表关系图&#xff1a; 例题&#xff1a; 1.查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。 2.列出所有员工的姓名及其直接上级的姓名。 3.列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称。 4.列出部门名称和这些部门的员工信…

YOLOv8 测试 5-2:Linux 中 Dockerfile 部署 YOLOv8 项目一键运行,Python 封装 API 接口测试

一、前言 记录时间 [2024-4-15] 系列文章简摘&#xff1a; Docker 学习笔记&#xff08;二&#xff09;&#xff1a;在 Linux 中部署 Docker&#xff08;Centos7 下安装 docker、环境配置&#xff0c;以及镜像简单使用&#xff09; API 接口简单使用&#xff08;二&#xff09;…

第十五届蓝桥杯复盘 pythonA组——试题A 拼正方形

思路 先把22的正方形放进去&#xff0c;剩余的地方用11的正方形填充 情况一&#xff1a; 假设所有的22 和11恰好拼成一个大正方形 但是上图的代码是不符合现实情况的 比如两个22和1个11 面积为9&#xff0c;是平方数&#xff0c;但是拼不成正方形&#xff0c; 因此要换思路&…

从零自制docker-9-【管道实现run进程和init进程传参】

文章目录 命令行中输入参数长度过长匿名管道从父进程到子进程传参[]*os.File{}os.NewFile和io.ReadAllexe.LookPathsyscall.Execstrings.Split(msgStr, " ")/bin/ls: cannot access : No such file or directory代码 命令行中输入参数长度过长 用户输入参数过长或包…

SOLIDWORKS 2024教育版全套多少钱?

SOLIDWORKS 2024教育版全套是一款专为教育机构和学生设计的3D CAD设计软件套装。它集合了SOLIDWORKS的核心功能和工具&#xff0c;旨在帮助学生在学习和实践过程中掌握先进的工程设计和制造技术。对于教育机构和学生而言&#xff0c;了解SOLIDWORKS 2024教育版全套的价格成为了…

深度探索:Secure Hash Algorithm(SHA)全景解析

title: 深度探索&#xff1a;Secure Hash Algorithm&#xff08;SHA&#xff09;全景解析 date: 2024/4/15 18:33:17 updated: 2024/4/15 18:33:17 tags: SHA安全抗碰撞性算法版本实现细节性能优化发展历史应用案例 密码学中的哈希函数 一、哈希函数的定义 哈希函数是一种数…

快来看!这样的统计地图真的很好绘制的~~

之前有小伙伴再讨论群里提问关于分级统计地图(choropleth maps) 的绘制方法&#xff0c;刚开始看到这个问题的时候觉得比较简单&#xff0c;就给出了几个处理方法&#xff0c;有R的也有基于Python 的&#xff0c;但后来和提问小伙伴一聊&#xff0c;才知道是要绘制一个有 ”三元…

2024五一杯数学建模C题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

四.音视频编辑-音频混合-概述

引言 当我们在前两篇博客中成功地构建了一个媒体组合&#xff0c;并且略过了音频部分时&#xff0c;我们意识到了我们需要对这个项目进行更详细的探讨。在本篇博客中&#xff0c;我们将会展示如何创建一个包含视频轨道、配音音频轨道以及背景音频轨道的完整媒体组合。更进一步…

lua 环境安装

下载地址&#xff1a; https://luabinaries.sourceforge.net/download.html 安装环境变量 检查一下是否安装成功&#xff0c;有版本号&#xff0c;打印一句话&#xff0c;如下表示成功 idea 安装插件&#xff0c;方便编写lua脚本 配置一下idea 运行测试 local function m…

经典文献阅读之--Light-LOAM( 基于图匹配的轻量级激光雷达里程计和地图构建)

0. 简介 将SLAM应用于机器人应用中&#xff0c;可靠性和效率是两个最受重视的特性。本文《Light-LOAM: A Lightweight LiDAR Odometry and Mapping based on Graph-Matching》考虑在计算能力有限的平台上实现可靠的基于激光雷达的SLAM功能。首先与大多数选择点云配准的显著特征…

国税发票查验接口、电子增值税发票查验接口、数电票查验接口

翔云发票查验接口支持增值税发票管理系统开具发票的真伪&#xff0c;通过发票代码、号码、日期、金额、校验码四要素信息进行真伪的查验&#xff0c;支持返回全票面信息&#xff0c;API接口便于集成&#xff0c;可适用于多种应用场景。 发票查验接口python调用示例&#xff1a;…

正则表达式(Regular Expression)

正则表达式很重要&#xff0c;是一个合格攻城狮的必备利器&#xff0c;必须要学会&#xff01;&#xff01;&#xff01; &#xff08;参考视频&#xff09;10分钟快速掌握正则表达式&#xff08;奇乐编程学院&#xff09;https://www.bilibili.com/video/BV1da4y1p7iZ在线测试…

分布式监控平台---Zabbix

一、Zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监控软件&#xff0c;我们可以&#xff1a; 通过一个友好的界面进行浏览整个…

CSRF漏洞详解

目录 什么是同源策略 什么是csrf CSRF 攻击会产生什么影响&#xff1f; CSRF漏洞low等级复现 什么是同源策略 协议相同 域名相同 端口相同 什么是csrf 跨站请求伪造&#xff08;也称为 CSRF&#xff09;是一种 Web 安全漏洞&#xff0c;允许攻击者诱导用户执行他们不打…

华为各级OD薪资曝光。。

华为 OD 薪资 之前写过几篇华为 OD 的算法题&#xff0c;后来有不少同学问起&#xff0c;华为 OD 薪资到底怎么样。 华为 OD 的薪资待遇&#xff0c;网上信息不多&#xff0c;只找到一篇相对靠谱的爆料&#xff1a; 上述是月 base 的爆料&#xff0c;然后通常 OD 是 15-16 薪。…