算法学习一,基础查找算法和排序算法

算法学习一,基础查找算法和排序算法

你提供的代码示例展示了两种常见的哈希表实现方法:拉链法(Separate Chaining)和线性探测法(Linear Probing)。每种方法都有其优缺点,适用于不同的场景。

拉链法(Separate Chaining)

拉链法通过将每个散列值对应的位置存储一个链表来解决冲突。这种方法的优点是简单且实现灵活,可以使用任何数据结构来存储冲突的键值对。以下是拉链法的主要特点:

  1. 优点

    • 简单且实现灵活。
    • 不会像线性探测那样导致同类哈希的聚集。
  2. 缺点

    • 需要额外的空间来存储链表。

代码示例(使用拉链法):

namespace StructScript { /// <summary> /// 哈希表的查找算法主要分为两步: /// 第一步是用哈希函数将键转换为数组的一个索引,理想情况下不同的键都能转换为不同的索引值,但是实际上会有多个键哈希到到相同索引值上。 /// 因此,第二步就是处理碰撞冲突的过程。这里有两种处理碰撞冲突的方法:separate chaining(拉链法)和linear probing(线性探测法)。 /// 拉链法: /// 使用链表来解决冲突 /// </summary> public class HashSearch2<T> { private int mCount = 16; // 线性探测表的大小 private List<T>[] mValues; public HashSearch2() { mValues = new List<T>[mCount]; for (int i = 0; i < mCount; i++) { mValues[i] = new List<T>(); } } private int HashCode(T value) { return (value.GetHashCode() & 0xFFFFFFF) % mCount; } public void Add(T value) { // 当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1 int index = HashCode(value); if (!mValues[index].Contains(value)) { mValues[index].Add(value); } } public bool Contains(T value) { // 当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1 int index = HashCode(value); return mValues[index].Contains(value); } } } 

线性探测法(Linear Probing)

线性探测法通过在冲突发生时,直接检查散列表中的下一个位置来解决冲突。这种方法的优点是简单,但会形成聚集现象,导致后续插入和查找操作的性能下降。

  1. 优点

    • 实现简单。
  2. 缺点

    • 会导致同类哈希的聚集。
    • 插入和查找操作在发生冲突时需要进行多次检查,性能下降。

代码示例(使用线性探测法):

namespace StructScript { /// <summary> /// 哈希表的查找算法主要分为两步: /// 第一步是用哈希函数将键转换为数组的一个索引,理想情况下不同的键都能转换为不同的索引值,但是实际上会有多个键哈希到到相同索引值上。 /// 因此,第二步就是处理碰撞冲突的过程。这里有两种处理碰撞冲突的方法:separate chaining(拉链法)和linear probing(线性探测法)。 /// 线性探测法: /// 使用大小为M的数组来保存N个键值对,我们需要使用数组中的空位解决碰撞冲突 /// 当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1 /// 线性探测虽然简单,但是有一些问题,它会导致同类哈希的聚集。在存入的时候存在冲突,在查找的时候冲突依然存在 /// </summary> public class HashSearch2<T> { private int mCount = 16; // 线性探测表的大小 private T[] mValues; public HashSearch2() { mValues = new T[mCount]; } private int HashCode(T value) { return (value.GetHashCode() & 0xFFFFFFF) % mCount; } public void Add(T value) { // 当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1 for (int i = 0; i < mCount; i++) { int index = (HashCode(value) + i) % mCount; if (mValues[index] == null || mValues[index].Equals(default(T))) { mValues[index] = value; break; } } } public bool Contains(T value) { // 当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1 for (int i = 0; i < mCount; i++) { int index = (HashCode(value) + i) % mCount; if (mValues[index] != null && mValues[index].Equals(value)) { return true; } if (mValues[index] == null) { break; } } return false; } } } 

总结

  • 拉链法:通过链表解决冲突,简单且实现灵活,但需要额外的空间。
  • 线性探测法:通过直接检查下一个位置解决冲突,实现简单但会导致聚集现象。

选择哪种方法取决于具体的应用场景和性能要求。如果对内存使用有较高要求,可以选择拉链法;如果对性能要求较高,可以考虑其他更复杂的哈希表实现方法,如双散列法(Double Hashing)或二次探测法(Quadratic Probing)。

Read more

使用现代C++构建高效日志系统的分步指南

使用现代C++构建高效日志系统的分步指南

使用现代C++构建高效日志系统的分步指南 * 1. 确定日志系统的需求和目标 * 2. 设计日志系统的架构 * 3. 实现阶段 * 3.1 实现日志管理器(LogManager) * 3.2 实现日志记录器(Logger) * 3.3 实现日志格式化器(Formatter) * 3.4 实现日志输出器(Outputter) * 3.5 实现日志文件轮转 * 3.6 实现异常处理 * 3.7 实现性能优化 * 4. 测试和验证 * 5. 文档编写 * 6. 总结 在软件开发中,日志系统扮演着关键角色,帮助开发者记录程序运行状态、调试问题以及监控系统性能。使用现代C++构建一个高效且灵活的日志系统,不仅可以提升开发效率,还能增强程序的可维护性和可靠性。以下是构建这样一个日志系统的详细分步指南: 1. 确定日志系统的需求和目标

By Ne0inhk
深入解剖STL map/multimap:接口使用与核心特性详解

深入解剖STL map/multimap:接口使用与核心特性详解

❤️@燃于AC之乐 来自重庆 计算机专业的一枚大学生 ✨专注 C/C++ Linux 数据结构 算法竞赛 AI 🏞️志同道合的人会看见同一片风景! 👇点击进入作者专栏: 《算法画解》 ✅ 《linux系统编程》✅ 《C++》 ✅ 🌟《算法画解》算法相关题目点击即可进入实操🌟 感兴趣的可以先收藏起来,请多多支持,还有大家有相关问题都可以给我留言咨询,希望希望共同交流心得,一起进步,你我陪伴,学习路上不孤单! 文章目录 * 前言(map系列容器概述) * 一、map类介绍 * 1.1 map的类模板声明 * 二、pair类型介绍 * 2.1 pair的结构定义 * 2.2 pair的使用要点 * 三、map的构造与迭代器 * 3.1 构造接口 * 3.2 迭代器接口 * 四、map的增删查操作

By Ne0inhk
2025信奥赛C++提高组csp-s复赛真题及题解:社团招新

2025信奥赛C++提高组csp-s复赛真题及题解:社团招新

2025信奥赛C++提高组csp-s复赛真题及题解:社团招新 题目描述 小 L 是学校算法协会的成员。在今年的学校社团招新中,小 L 一共招收了 n n n 个新成员,其中 n n n 为偶数。现在小 L 希望将他们分到协会不同的部门。 算法协会共设有三个部门,其中第 i i i ( 1 ≤ i ≤ n 1 \leq i \leq n 1≤i≤n) 个新成员对第 j j j ( 1 ≤ j ≤ 3 1 \leq j \leq

By Ne0inhk

Java全栈开发工程师的实战面试:从基础到高阶

Java全栈开发工程师的实战面试:从基础到高阶 在一次真实的面试中,一位名叫李晨的28岁程序员接受了某互联网大厂的Java全栈开发岗位的面试。他拥有计算机科学与技术硕士学位,拥有5年左右的开发经验,曾就职于一家知名电商公司,主要负责前后端架构设计和核心业务模块的开发。他的工作职责包括:基于Spring Boot构建微服务系统、使用Vue3进行前端组件化开发以及通过Kubernetes部署和维护应用。他的项目成果包括:优化了订单处理流程,使系统的并发吞吐量提升了30%;并主导了一个基于TypeScript的前端框架重构,提高了代码可维护性。 面试官:李晨,你好,欢迎来到我们公司的面试。首先,请你简单介绍一下你自己。 李晨:好的,我叫李晨,28岁,本科毕业于XX大学,硕士就读于XX大学的计算机科学与技术专业。我有5年左右的开发经验,目前在一家电商平台担任Java全栈开发工程师。我的主要职责是搭建和维护后端服务,同时参与前端框架的设计和实现。在工作中,我主导过多个项目的开发,并取得了一些不错的成果。 面试官:非常好,那么我们先从Java的基础开始聊起。你能说说Java 8之后引入

By Ne0inhk