基于顺序表 --- 实现简易【通讯录】

news2024/11/17 23:24:34

1. 多文件操作

SeqList.h //用于定义顺序表的结构,增删查改等函数的声明
SeqList.c //用于实现增删查改等函数
Contact.h //用于定义通讯录的结构,通讯录中联系人的增删查改等函数的声明
Contact.c //用于实现通讯录中增删查改等函数
Test.h //用于测试上述实现的函数,和菜单界面

2. 通讯录的主要功能

1.初始化通讯录
2.销毁通讯录
3.展示联系人数据
4.增加联系人数据
5.判断指定联系人是否存在
6.删除联系人数据
7.查找联系人数据
8.修改联系人数据

对通讯录中各个功能的展示:
在这里插入图片描述

3. 通讯录的实现

想要基于顺序表实现通讯录,首先我们需要一个顺序表。由于顺序表的实现比较简单,这里直接给出,不进行详细说明 (如想要详细了解顺序表的实现,请前往我的主页查看)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ddb3977b5f2740a7bbdc3e4a4f8d10dc.png

说明:下面两个文件中注释的部分是在顺序表类型替换后(由整型替换为结构体类型)的不适用的部分。读者不必在意。

SeqList.h

在这个头文件中由于要用上Contact.h中定义的peoInfo,所以要包含Contact.h

#pragma once

#include <stdio.h>
#include  <stdlib.h>
#include <assert.h>
#include "Contact.h"

//typedef int SQDataType;
typedef peoInfo SQDataType;

typedef struct SeqList
{
	SQDataType* arr;
	int size;
	int capacity;
}SL;

void SLInit(SL* ps);

void SLDestory(SL* ps);

//void SLPrint(SL ps);

void SLPushBack(SL* ps, SQDataType x);

void SLPushFront(SL* ps, SQDataType x);

void SLPopBack(SL* ps);

void SLPopFront(SL* ps);

//void SLFind(const SL* ps, SQDataType x);

void SLInsert(SL* ps, int pos, SQDataType x);

void SLErase(SL* ps, int pos);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 

#include "SeqList.h"

void SLInit(SL* ps)
{
	ps->arr = (SQDataType*)malloc(sizeof(SQDataType) * 4);
	if (ps->arr == NULL)
	{
		perror("malloc fail!\n");
		return ;
	}

	ps->capacity = 4;
	ps->size = 0;

}

void SLDestory(SL* ps)
{
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

void CheckCapacity(SL* ps,SQDataType x)
{
	if (ps->size == ps->capacity)
	{
		SQDataType* tmp = (SQDataType*)realloc(ps->arr, sizeof(SQDataType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail!\n");
			return ;
		}
		else
		{
			ps->arr = tmp;
			ps->capacity *= 2;
		}
	}
}

//void SLPrint(SL ps)
//{
//	for (int i = 0; i < ps.size; i++)
//	{
//		printf("%d ", ps.arr[i]);
//	}
//	printf("\n");
//
//}

void SLPushBack(SL* ps, SQDataType x)
{
	assert(ps);
	CheckCapacity(ps, x);

	ps->arr[ps->size] = x;
	ps->size++;
}

void SLPushFront(SL* ps, SQDataType x)
{
	assert(ps);
	CheckCapacity(ps, x);

	int i = ps->size;
	for (i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}

	ps->arr[i] = x;
	ps->size++;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	if (ps->size == 0)
	{
		printf("无数据可删除!\n");
		return;
	}

	ps->size--;
}

void SLPopFront(SL* ps)
{
	assert(ps);
	if (ps->size == 0)
	{
		printf("无数据可删除!\n");
		return;
	}

	for (int i = 0; i < ps->size; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//void SLFind(const SL* ps, SQDataType x)
//{
//	assert(ps);
//	if (ps->size == 0)
//	{
//		printf("无数据!\n");
//		return;
//	}
//
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			printf("找到了\n");
//			return;
//		}
//	}
//
//	printf("找不到\n");
//}

void SLInsert(SL* ps, int pos, SQDataType x)
{
	assert(ps && pos < ps->size && ps->size>0);
	CheckCapacity( ps, x);

	int i = ps->size;
	for ( i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[i] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
	assert(pos < ps->size && ps->size>0);

	for (int i = pos; i < ps->size; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

1.定义通讯录的结构
这里一定不能忽略前置声明,前置声明的意思是告诉这个头文件我们存在这个顺序表,并且可以使用。

要用到顺序表相关的方法,对通讯录的操作实际上就是对顺序表的操作。
有了前置声明,下面的 Contact * con 就是顺序表中的 SL*sl。

#pragma once

#include <stdio.h>
#include <string.h>

#define MAX_NAME 10
#define MAX_GENDER 10
#define MAX_TEL 20
#define MAX_ADDR 20


//定义联系人数据结构:姓名+性别+年龄+电话+地址
typedef struct PeosonInfo
{
	char name[MAX_NAME];
	char gender[MAX_GENDER];
	int age;
	char tel[MAX_TEL];
	char addr[MAX_ADDR];
}peoInfo;

//前置声明
typedef struct SeqList Contact;
//给顺序表改个名字,叫做通讯录
//注意:这里不能写做typedef SL Contact,而是要用原名。
//因为SL是在struct SeqList定义好了之后才重命名的


//要用到顺序表相关的方法,对通讯录的操作实际上就是对顺序表的操作
//有了前置声明,下面的 Contact* con 就是顺序表中的 SL*sl

2.初始化通讯录

void InitContact(Contact* con)//就是相当于SL* sl
{
	//实际上就是顺序表的初始化
	SLInit(con);
}

3.销毁通讯录

void DestroyContact(Contact* con)
{
	SLDestory(con);
}

4.展示联系人数据

展示联系人不能改变其数据内容,所以可以加const进行保护。

void ShowContact(const Contact* con)
{
	//表头:姓名+性别+年龄+电话+地址
	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");

	for (int i = 0; i < con->size; i++)
	{
		printf("%-5s %-5s %-5d %-5s %-5s\n",
			    con->arr[i].name,
			    con->arr[i].gender, 
			    con->arr[i].age, 
			    con->arr[i].tel,
				con->arr[i].addr);
	} 
	printf("\n");
}

5.增加联系人数据

增加通讯录中联系人的数据,实际上就是对顺序表的插入操作,可以使用头插和尾插。这里是尾插。

void AddContact(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);//与顺序表中尾插函数的参数对应
}

6.判断指定联系人是否存在
这个函数是在删除联系人查找联系人修改联系人中使用的,因为这三个操作都要先判断该联系人是否存在。若存在,则返回该联系人的位置下标,若不存在则返回-1。

int FindByname(const Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}

7.删除联系人数据

删除之前要判断这个人是否存在通讯录中,如果这个人存在,说明我们知道他的位置,直接复用顺序表中的对应函数进行删除。

void DelContact(Contact* con)
{
	//1.判断要删除的人是否存在
	char name[MAX_NAME];
	printf("请输入要删除人的姓名:\n");
	scanf("%s",name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}

	//2.删除:知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
	printf("\n");
}

8.查找联系人数据
在查找之前也要先判断该联系人是否存在,若存在,则打印出该联系人的全部信息;若不存在,则进行提示。

void FindContact(const Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要查找的人的姓名:\n");
	scanf("%s", name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要查找的人不存在!\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");

		printf("%-5s %-5s %-5d %-5s %-5s\n", 
			con->arr[find].name,
			con->arr[find].gender,
			con->arr[find].age,
			con->arr[find].tel,
			con->arr[find].addr);

		printf("\n");
}

9.修改联系人数据
修改联系人之前也要判断此人是否存在,存在才修改,不存在则进行提示。

void ModifyContact(Contact* con)
{
	//1.判断要修改的联系人是否存在
	char name[MAX_NAME];
	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");
	printf("\n");

}

4. 通讯录完整代码

Contact.h

#pragma once

#include <stdio.h>
#include <string.h>

#define MAX_NAME 10
#define MAX_GENDER 10
#define MAX_TEL 20
#define MAX_ADDR 20


//定义联系人数据结构:姓名+性别+年龄+电话+地址
typedef struct PeosonInfo
{
	char name[MAX_NAME];
	char gender[MAX_GENDER];
	int age;
	char tel[MAX_TEL];
	char addr[MAX_ADDR];
}peoInfo;

//前置声明
typedef struct SeqList Contact;
//给通讯录改个名字,叫做通讯录
//注意:这里不能写做typedef SL Contact,而是要用原名。
//因为SL是在struct SeqList定义好了之后才重命名的


//要用到顺序表相关的方法,对通讯录的操作实际上就是对顺序表的操作
//有了前置声明,下面的 Contact* con 就是顺序表中的 SL*sl

//初始化通讯录
void InitContact(Contact* con);

//添加通讯录数据
void AddContact(Contact* con);

//删除通讯录数据
void DelContact(Contact* con);

//展示通讯录数据
void ShowContact(const Contact* con);

//查找通讯录数据
void FindContact(const Contact* con);

//修改通讯录数据
void ModifyContact(Contact* con);

//销毁通讯录数据
void DestroyContact(Contact* con);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Contact.h"
#include "SeqList.h"

//初始化通讯录
void InitContact(Contact* con)//就是相当于SL* sl
{
	//实际上就是顺序表的初始化
	SLInit(con);
}

//销毁通讯录数据
void DestroyContact(Contact* con)
{
	SLDestory(con);
}

//添加通讯录数据
void AddContact(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);//与顺序表中尾插函数的参数对应
}

//展示通讯录数据
void ShowContact(const Contact* con)
{
	//表头:姓名+性别+年龄+电话+地址
	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");

	for (int i = 0; i < con->size; i++)
	{
		printf("%-5s %-5s %-5d %-5s %-5s\n",
			    con->arr[i].name,
			    con->arr[i].gender, 
			    con->arr[i].age, 
			    con->arr[i].tel,
				con->arr[i].addr);
	} 
	printf("\n");
}

int FindByname(const Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}


//删除指定位置通讯录数据
void DelContact(Contact* con)
{
	//1.判断要删除的人是否存在
	char name[MAX_NAME];
	printf("请输入要删除人的姓名:\n");
	scanf("%s",name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}

	//2.删除:知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
	printf("\n");
}

//修改通讯录数据
void ModifyContact(Contact* con)
{
	//1.判断要修改的联系人是否存在
	char name[MAX_NAME];
	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");
	printf("\n");

}

//查找通讯录数据
void FindContact(const Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要查找的人的姓名:\n");
	scanf("%s", name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要查找的人不存在!\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");

		printf("%-5s %-5s %-5d %-5s %-5s\n", 
			con->arr[find].name,
			con->arr[find].gender,
			con->arr[find].age,
			con->arr[find].tel,
			con->arr[find].addr);

		printf("\n");
}

Test.c

void menu()
{
	printf("**************    通讯录    *************\n");
	printf("******* 1.添加联系人  2.删除联系人 *******\n");
	printf("******* 3.查找联系人  4.修改联系人 *******\n");
	printf("******* 5.展示联系人  0.退出通讯录   *****\n");
	printf("******************************************\n");

}

enum option
{
	Exit,
	addcontact,
	delcontact,
	findcontact,
	modifycontact,
	showcontact
};

int main()
{
	//TestSeqList();
	//ContactTest();

	Contact con;
	InitContact(&con);

	int input = 1;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);

		switch (input)
		{
		case Exit:
			printf("退出通讯录!\n");
			break;
		case addcontact:
			AddContact(&con);
			break;
		case delcontact:
			DelContact(&con);
			break;
		case findcontact:
			FindContact(&con);
			break;
		case modifycontact:
			ModifyContact(&con);
			break;
		case showcontact:
			ShowContact(&con);
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}

	} while (input);

	return 0;
}

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

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

相关文章

重磅!openGauss6.0创新版本,带着新特性正式发布了!

&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&#x1f61c;&#x1f61c; 中国DBA联盟(ACD…

最新社交相亲系统源码PHP

最新社交相亲系统源码PHP 安装环境&#xff1a; php7.2 mysql 5.7 框架&#xff1a; 后端thinkphp6 前端&#xff1a;jquery layui PC 移动端响应式 线上案例&#xff1a;https://cjr.oemsun.com/ 主要页面及功能预览 首页 相亲资料详情页 红娘跟进记录 海报、一键复制分…

实操:Dropzone.js实现文件上传

&#x1f3e0;官网 点我前往 &#x1f953;依赖 <script src"https://unpkg.com/dropzone5/dist/min/dropzone.min.js"></script> <link rel"stylesheet" href"https://unpkg.com/dropzone5/dist/min/dropzone.min.css" type&…

STL——vector容器基本使用与常用接口模拟实现

vector的介绍及使用 vector的介绍 vector是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的…

自然语言处理NLP概述

大家好&#xff0c;自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向&#xff0c;其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将从自然语言处理的本质、原理和应用三个方面&#xff0c;对其进行概述。 一、NLP的本质 NLP是一种…

神经网络学习笔记10——RNN、ELMo、Transformer、GPT、BERT

系列文章目录 参考博客1 参考博客2 文章目录 系列文章目录前言一、RNN1、简介2、模型结构3、RNN公式分析4、RNN的优缺点及优化1&#xff09;LSTM是RNN的优化结构2&#xff09;GRU是LSTM的简化结构 二、ELMo1、简介2、模型结构1&#xff09;输入2&#xff09;左右双向上下文信…

【史上最细教程】 Typora+PicGo+Gitee 实现发给别人的Typora笔记也能看到图片

文章目录 问题描述前提准备&#xff1a;操作步骤&#xff1a;1.Gitee新建项目作为图床、获取仓库访问密钥2.PicGo连接Gitee图床3.Typora连接PicGo 问题描述 Typora记录的笔记&#xff0c;图片保存默认在本地&#xff0c;这时候复制出来上传CSDN、或发给别人的时候图片就是空链…

Qt 的发展历史、现状与启示

Qt 最早在1991年由挪威的两位程序员 Eirik Chambe-Eng 和 Haavard Nord 开发&#xff0c;他们在1994年创立 Trolltech 公司&#xff08;奇趣科技&#xff09;正式经营软件业务。Qt 的第一个公众预览版于1995年面世&#xff0c;之后在2008年被诺基亚收购&#xff1b;2011年到201…

【漏洞复现】万户 ezOFFICE wf_printnum SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

Linux :进程的程序替换

目录 一、什么是程序替换 1.1程序替换的原理 1.2更改为多进程版本 二、各种exe接口 2.2execlp ​编辑 2.2execv 2.3execle、execve、execvpe 一、什么是程序替换 1.1程序替换的原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往…

【Redis系列】Redis安装与使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【群晖】NASTOOL-自动化处理影音视频工具

【群晖】NASTOOL-自动化处理影音视频 本文主要从获取、部署、使用、配置等方面进行手把手教学如何使用nastool工具进行影音视频自动化处理。从此靠别繁琐的网上各个网址找资源-下载-复制-改名-刮削等操作。 准备 DSM 7.1 &#xff08;我使用的是群晖 7.1 系统&#xff0c;不管…

JVM剖析

0.前言 Java 是当今世界使用最广泛的技术平台之一。使用 Java 或 JVM 的一些技术包括&#xff1a; Apache spark用于大数据处理&#xff0c;数据分析在JVM上运行;用于数据流的Apache NiFi在内部使用的也是 JVM;现代 Web 和移动应用程序开发中使用的React native使用 的也包含…

【代码篇】事件监听函数的内存泄漏,都给我退散吧!

前言 内存泄漏是个很严肃的问题&#xff0c;可是迄今也没有一个非常有效的排查方案&#xff0c;本方案就是针对性的单点突破。 工作中&#xff0c;我们会对window, DOM节点&#xff0c;WebSoket, 或者单纯的事件中心等注册事件监听函数, 添加了&#xff0c;没有移除&#xff…

网络爬虫:爬取假数据

网络爬虫&#xff1a;爬取假数据 文章目录 网络爬虫&#xff1a;爬取假数据前言一、项目介绍&#xff1a;二、项目来源&#xff1a;三、架构图&#xff1a;&#xff08;流程图&#xff09;四、使用了什么技术&#xff1a;&#xff08;知识点&#xff09;五、结果示意图&#xf…

网络安全 | 什么是单点登录SSO?

关注WX&#xff1a;CodingTechWork SSO-概念 单点登录 (SSO) 是一种身份认证方法&#xff0c;用户一次可通过一组登录凭证登入会话&#xff0c;在该次会话期间无需再次登录&#xff0c;即可安全访问多个相关的应用和服务。SSO 通常用于管理一些环境中的身份验证&#xff0c;包…

obs直播推流 + ffmpeg参数

OBS 启动参数设为 --startstreaming &#xff0c; 可以让它启动后自动开始直播 对应ffmpeg参数&#xff1a; echo off :loop ffmpeg -re -i a.mp4 -r 24 -c:v libx264 -preset ultrafast -profile:v baseline -g 24 -keyint_min 24 -x264-params nal-hrdcbr -b:v 2500k -minr…

线上研讨会 | 应对汽车毫米波雷达设计中的电磁挑战

智能汽车、新能源汽车最近几年一直是汽车行业关注的热点&#xff0c;随着5G技术越来越普及&#xff0c;汽车智能化发展将越来越迅速。从传统汽车到智能汽车&#xff0c;不是简单功能的增强&#xff0c;而是从单一功能的交通工具变成可移动的办公和娱乐空间&#xff0c;成为物联…

蓝桥杯python组真题练习1

目录 1.单词分析 2.成绩统计 3.门牌制作 4.卡片 5.跑步训练 6.蛇形填数 7.时间显示 1.单词分析 1.单词分析 - 蓝桥云课 (lanqiao.cn) s list(input()) maxx 0 for i in s:num s.count(i)if num>maxx:sm imaxx numif num maxx:if ord(sm)>ord(i):sm i print…

AcWing-孤独的照片

4261. 孤独的照片 - AcWing题库 所需知识&#xff1a;贡献法 整体思路&#xff1a;首先想到暴力枚举所有区间&#xff0c;判断每个区间内是否有一种牛的数量是一只&#xff08;提前用前缀和存放每个位置及以前的牛的数量&#xff09; C代码&#xff1a;&#xff08;过不了&a…