Java深入了解数据结构之哈希表篇

Java深入了解数据结构之哈希表篇

1. 哈希表的定义

哈希表(Hash Table),也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数(Hash Function)。

哈希表是基于哈希函数实现的,哈希函数将关键字映射到哈希表中的位置,如果存在两个关键字映射到同一个位置,则发生碰撞。

2. 哈希表的工作原理

哈希表的工作原理可以分为以下几个步骤:

  1. 建立哈希表。
  2. 根据哈希函数把关键字映射到表的位置。
  3. 如果该位置已经有其他关键字占用,则发生碰撞。
  4. 碰撞解决(拉链法,开放地址法等)。
  5. 查找记录:根据关键字计算哈希值,找到对应的数据。

3. 哈希表的特点

哈希表的特点:

  1. 查找/插入/删除的时间复杂度都是O(1)的。
  2. 哈希表大小一般为素数,可以有效避免哈希冲突。
  3. 哈希表的哈希函数应该尽量少的发生哈希冲突。

4. 哈希表的实现

哈希表的实现有多种方法,比如:

  1. 拉链法
  2. 线性探测法
  3. 双散列法

4.1 拉链法

拉链法是哈希表实现最为常用也最为简单的方法。拉链法把每个哈希值相同的元素都放到一个链表中,查询时遍历该链表,查找对应元素。

public class HashTable<T> {

    private int size;
    private LinkedList<T>[] table;

    public HashTable() {
        size = 17;
        table = new LinkedList[size];
    }

    public void put(T element) {
        int hash = element.hashCode() % size;
        if (table[hash] == null) {
            table[hash] = new LinkedList<>();
        }
        table[hash].add(element);
    }

    public T get(T element) {
        int hash = element.hashCode() % size;
        LinkedList<T> list = table[hash];
        if (list != null) {
            for (T e : list) {
                if (e.equals(element)) {
                    return e;
                }
            }
        }
        return null;
    }
}

4.2 线性探测法

线性探测法是一种开放地址法,也就是说,发生哈希冲突时,根据一定规则继续探测下一个位置,直到找到空位置或者查询结束为止。

public class LinearHashTable<T> {

    private int size;
    private Object[] table;

    public LinearHashTable() {
        size = 17;
        table = new Object[size];
    }

    public void put(T element) {
        int hash = element.hashCode() % size;
        while (table[hash] != null) {
            hash = (hash + 1) % size;
        }
        table[hash] = element;
    }

    public T get(T element) {
        int hash = element.hashCode() % size;
        while (table[hash] != null && !table[hash].equals(element)) {
            hash = (hash + 1) % size;
        }
        if (table[hash] != null) {
            return (T) table[hash];
        }
        return null;
    }
}

5. 示例说明

5.1 示例一

一种常见的使用哈希表的场景是在数据去重上。比如,去掉一个文件中的重复单词,可以使用哈希表来实现。

public static void main(String[] args) {
    try (Scanner scanner = new Scanner(new File("input.txt"), "UTF-8");
         PrintWriter writer = new PrintWriter("output.txt", "UTF-8")) {
        Set<String> set = new HashSet<>();
        while (scanner.hasNext()) {
            String word = scanner.next();
            if (!set.contains(word)) {
                set.add(word);
                writer.print(word + " ");
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

5.2 示例二

哈希表还广泛应用于快速查找。比如,在一堆卡片中查找编号为123456的卡片,可以使用哈希表来实现。

public static void main(String[] args) {
    Map<String, Card> map = new HashMap<>();
    List<Card> cards = new ArrayList<>();
    cards.add(new Card("123456", "xxx"));
    cards.add(new Card("654321", "yyy"));
    cards.add(new Card("111111", "zzz"));
    for (Card card : cards) {
        map.put(card.getId(), card);
    }
    Card target = map.get("123456");
    System.out.println(target.getName());
}
class Card {
    private String id;
    private String name;
    public Card(String id, String name) {
        this.id = id;
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java深入了解数据结构之哈希表篇 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Leetcode Practice — 字符串

    目录 14. 最长公共前缀 思路解析 151. 反转字符串中的单词 思路解析 125. 验证回文串 思路解析 415. 字符串相加 思路解析 3. 无重复字符的最长子串 思路解析 8. 字符串转换整数 (atoi) 思路解析 14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 输入:strs = […

    算法与数据结构 2023年4月18日
    00
  • 【牛客小白月赛70】A-F题解【小d和超级泡泡堂】【小d和孤独的区间】【小d的博弈】【小d和送外卖】

    比赛传送门:https://ac.nowcoder.com/acm/contest/53366 难度适中。 ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 阅读原文获得更好阅读体验:https://www.erikt…

    算法与数据结构 2023年4月17日
    00
  • 浅谈Python描述数据结构之KMP篇

    浅谈Python描述数据结构之KMP篇 简介 本篇文章将着重介绍KMP算法,其中包含KMP算法的基本原理、实现步骤以及Python代码实现示例。KMP算法是一种高效的字符串匹配算法,它可以在O(m+n)的时间内完成字符串的匹配操作,其中m和n分别为主串和模式串的长度。 基本原理 KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,它的…

    数据结构 2023年5月17日
    00
  • Java数据结构之List的使用总结

    非常感谢您对本网站的关注。Java数据结构之List的使用总结是一个非常重要的主题,这里将为您详细介绍。 1. List是什么 在Java中,List是一种非常实用的数据结构,它代表了一个元素的有序集合,其中的每个元素都可以用一个整数索引来标识。List允许多个元素重复,同时还可以在集合的任意位置插入或者删除元素。 Java中的List主要分为两类:Arra…

    数据结构 2023年5月17日
    00
  • c#解析jobject的数据结构

    下面我将从以下几个方面,详细讲解如何使用C#解析JObject的数据结构。 1. 什么是JObject JObject 是 JSON.NET 库中的一个类,用于处理Json格式数据。它表示一个 JSON 对象,可以通过键值对的形式来描述一个 JSON 对象,并在其中包含 JSON 数组。JObject对象是动态类型,允许在运行时动态添加、修改或删除对象的属性…

    数据结构 2023年5月17日
    00
  • C语言数据结构实现链表逆序并输出

    下面是C语言数据结构实现链表逆序并输出的完整攻略。 1. 题目分析 本题目要求实现对链表的逆序,并依次输出各节点的值。而链表的逆序可以通过改变各节点之间的连接方式来实现。 2. 思路分析 创建一个指针,指向原链表的头结点。 遍历链表,将每个节点的next指针指向它前面的节点,从而实现链表的逆序。 遍历逆序后的链表,从头结点开始,依次输出每个节点的值。 3. …

    数据结构 2023年5月17日
    00
  • Redis中5种数据结构的使用场景介绍

    下面是详细的攻略: Redis中5种数据结构的使用场景介绍 Redis是一个高性能的无类型的键值数据库,支持多种数据结构。在使用Redis时,了解各种数据结构的使用场景,可以帮助我们更好地使用Redis。 1. String String是Redis最基本的数据结构,可以存储字符串、整数和浮点数,最大长度为512MB。 使用场景: 存储单个值,如用户ID、用…

    数据结构 2023年5月17日
    00
  • MySQL索引背后的数据结构及算法原理详解

    《MySQL索引背后的数据结构及算法原理详解》是一篇介绍MySQL索引背后的数据结构和算法原理的文章。MySQL索引是提高查询效率的一个重要工具,理解其背后的数据结构和算法原理对于提高数据库性能和优化查询操作是非常有帮助的。 本文主要分为以下三部分: MySQL索引背后的数据结构 索引的几种常见数据结构及其优缺点 索引的算法原理 MySQL索引背后的数据结构…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部