`
shenyu
  • 浏览: 122592 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

HashTable 基于链表地址法

 
阅读更多

功能上于前面两个HashTable(-)HashTable(二) 一致,但实现上采用的链表表示每个Hash桶的位置,这样理论上不用考虑容量问题。实际中HashTable中的每个SortLink太长会导致效率低下,因此HashTable的初始大小比较重要。

链表使用的是有序链表SortLink,这样查找,删除的效率会提高一半,但是新增则会从O(1)降到链表的平均长度的一半。考虑链表不是太长,所以不会对效率产生太大的影响。但终究来说,这种实现更适合查询,不适合大量反复的插入。

关于可以插入的数据的键值,此处假设为整数。

代码中有许多辅助类

其中:

Item:装载有key(关键值)的数据

Node:单向链表的节点

SortLink:单向单端有序链表

HashTable:Hash表

其中SortLink,HashTable中的print方法纯粹是为了测试使用。

HashTable.main提供测试方法

class Item {
    private int key;
    private Object value;
   
    public Item(int key, Object value) {
        this.key = key;
        this.value = value;
    }

    public int key() { return key; }
    public Object value()  { return value; }
}

class Node {
    private Item item;
    private Node next;

    public Node(Item item) {
        this.item = item;
    }
   
    public Item item() {
        return item;
    }

    public void next(Node next) {
        this.next = next;
    }

    public Node next() {
        return next;
    }
}

class SortLink {
    private Node first;
    public void add(Item item) {
        Node node = new Node(item);
           
        Node previous = null;
        Node current = first;
        while(current != null && current.item().key() < item.key()) {
            previous = current;
            current = current.next();
        }
        node.next(current);
        if (previous == null) first = node;
        else previous.next(node);
    }

    public Item remove(int key) {
        if(first ==  null) return null;
        Node previous = null;
        Node current = first;
        while(current != null && current.item().key() < key) {
            previous = current;
            current = current.next();
        }
        if(current != null && current.item().key() == key) {
            Item result = current.item();
            if(previous == null) first = current.next();
            else previous.next(current.next());
            return result;
        }
        return null;
    }

    public Item find(int key) {
        if(first == null) return null;
        Node current = first;
        while(current != null && current.item().key() < key) 
            current = current.next();
        if(current != null && current.item().key() == key) return current.item();
        else return null;
    }

    //测试专用
    void print() {
        Node current = first;
        while(current != null) {
            System.out.print(current.item().key() + ",");
            current = current.next();
        }
        System.out.println();
    }
}

class HashTable {
    private SortLink[] array;
    HashTable(int size) {
        array = new SortLink[size];
    }
    private int getHash(int key) {
        return key % array.length;
    }
    public void add(Item item) {
        int pos = getHash(item.key());
        if(array[pos] == null) array[pos] = new SortLink();
        array[pos].add(item);
    }

    public Item remove(int key) {
        int pos = getHash(key);
        if(array[pos] == null)return null;
        else return array[pos].remove(key);
    }

    public Item find(int key) {
        int pos = getHash(key);
        if(array[pos] == null)return null;
        else return array[pos].find(key);
    }

    //测试专用
    public void print() {
        for(int i=0; i<array.length; i++) {
            if(array[i] != null) array[i].print();
        }
    }
    public static void main(String[] args) {
        HashTable t = new HashTable(5);
        t.add(new Item(1,"hello"));
        t.add(new Item(6,"world"));
        t.add(new Item(11,"temp"));
        t.add(new Item(3,"jason"));
        t.add(new Item(104,"orange"));
        t.add(new Item(9,"peter"));
        t.print();

        System.out.println("====================");

        assert t.find(6).value().equals("world");
        assert t.find(11).value().equals("temp");
        assert t.find(104).value().equals("orange");
        assert t.find(9).value().equals("peter");
        assert t.find(87) == null;
        assert t.remove(3).value().equals("jason");
        assert t.find(3) ==  null;
        assert t.remove(6).value().equals("world");
        assert t.find(6) ==  null;
        t.print();
        System.out.println("====================");
       
        t.add(new Item(6,"temp"));
        assert t.find(6).value().equals("temp");
        t.print();
        System.out.println("==== OK ===");
    }
}

 

分享到:
评论

相关推荐

    HashMap和HashTable底层原理以及常见面试题

    2. 性能:HashMap的性能比HashTable好,因为HashMap使用数组和链表来存储键值对,而HashTable使用链表来存储键值对。 3. null键:HashMap允许存放null键和null值,而HashTable不允许存放null键和null值。 常见面试...

    HashTable的java实现

    在链表法中,每个数组元素都是一个链表的头节点。当一个键被哈希到某个特定位置时,这个键值对会被添加到对应位置链表的末尾。如果多个键被哈希到同一个位置,它们会在同一个链表中形成链接,解决了键冲突的问题。...

    HashTable

    查找操作同样计算哈希值,找到对应位置后,如果是链地址法,则需要遍历链表查找匹配的键。 4. 删除:删除操作涉及到如何找到要删除的键值对并从哈希表中移除。如果采用链地址法,可能需要遍历链表找到待删除节点,...

    哈希表hashtable实现

    在“hashtable.c”和“hashtable.h”中,很可能采用了链地址法,即每个数组元素实际上是一个链表的头节点,相同哈希值的元素会被链接在一起。 3. 插入操作:当向哈希表中插入元素时,首先计算键的哈希值,然后在...

    基于哈希链表的简单人员信息管理系统

    - **哈希表构建:** 采用质数取余法计算哈希值,利用链地址法解决哈希冲突。 - **插入方法:** 使用头插法,保证数据插入的高效性。 #### 三、项目功能详解 1. **员工信息的增加:** - **功能描述:** 管理员可...

    实例5 哈希表(Hashtable)和枚举器

    如果多个键的哈希值相同,就会发生哈希冲突,这时哈希表通常采用链地址法或者开放寻址法来解决冲突。 在Java的`Hashtable`中,每个键值对都是通过`Entry`对象来表示的,这些`Entry`对象构成了内部的哈希表。插入...

    Java容器类List、ArrayList、Vector及map、HashTable应用

    ArrayList和Vector都是基于数组的实现,LinkedList是基于链表的实现。ArrayList和Vector的主要区别在于Vector使用了synchronized方法,线程安全,而ArrayList则没有。 ArrayList是Java中最常用的List实现类,它提供...

    hashtable存储IP

    哈希表的工作原理基于哈希函数,它可以将任意大小的键(在本例中是IP地址)转化为固定大小的索引。这个索引用于在数组中定位对应的值。好的哈希函数能够将不同的键映射到不同的索引,减少冲突的可能性。在Java中,`...

    Java集合专题总结:HashMap 和 HashTable 源码学习和面试总结

    HashMap是一种基于哈希表的集合类,它的存储结构是一个数组,每个元素是一个单链表的头节点,链表用来解决hash地址冲突问题。HashMap有四个构造方法,其中初始容量和加载因子是影响性能的重要参数。加载因子是哈希表...

    基于C语言的数据结构-哈希表hashTable

    常见的方法有开放寻址法(线性探测、二次探测、双哈希探测等)和链地址法(每个槽位存储一个链表)。 二、C语言实现哈希表 1. 定义数据结构:首先,我们需要定义哈希表的结构体,通常包括数组、元素个数、装载因子...

    易语言哈希表例程 据java的HashTable编写

    当发生哈希冲突时,即两个键的哈希值相同,Java的HashTable使用链地址法处理,即将这些键值对放在同一个数组位置的链表中。 在易语言中实现哈希表,我们需要考虑以下几点: 1. **数据结构**:设计一个结构体或类来...

    希哈表C源代码工程hashtable

    在链地址法中,这可能意味着从链表中移除节点;在开放寻址法中,可能需要标记该位置为空。 在源代码工程中,可能会有以下关键文件和结构: - `hashtable.h`:头文件,定义哈希表的数据结构和公共接口。 - `...

    通用型哈希表HashTableT

    5. **链地址法**:一种常见的处理哈希冲突的方法,每个数组槽位都连接一个链表,所有哈希到同一位置的键值对会被挂在这个链表上。查找时,先计算键的哈希值,然后遍历对应的链表。 6. **开放寻址法**:当发生冲突时...

    Hashtable.rar

    在C#编程语言中,`Hashtable`是一种基于键值对的数据结构,它允许程序员存储和检索对象,通过关键字(key)来访问数据。本案例旨在深入解析`Hashtable`的使用方法,包括其基本操作、特点以及与其他数据结构的比较。 ...

    HashMap,HashTable,LinkedHashMap,TreeMap的区别

    TreeMap 是基于红黑树的数据结构,具有良好的性能和可扩展性。TreeMap 不允许键或值为 Null。 比较 在选择 Map 实现类时,需要考虑以下几个因素: * 是否需要同步?如果需要同步,可以选择 HashTable 或者使用 ...

    第9讲 对比Hashtable、HashMap、TreeMap有什么不同?1

    在面试中,HashMap的设计和实现细节是常见的考察点,例如哈希冲突的解决策略(开放寻址法和链地址法)、负载因子的影响、扩容机制以及树化改造的过程。当HashMap的桶内元素过多时,会将链表转化为红黑树,以优化查找...

    leetcode2-Algorithm:算法和数据结构练习

    Polynomial:基于链表的多项式类,支持+、-、*运算符。 Stack:基于链表的堆栈。 StackBasedOnArray:基于数组的堆栈。 队列:基于链表的队列。 QueueBasedOnArray:基于数组的队列。 PriorityQueue:基于链表的优先...

    12 HashTable.zip

    常见的解决策略有开放寻址法(线性探测、二次探测、双哈希探测等)和链地址法(每个槽位是一个链表,冲突的元素添加到链表中)。 3. **装载因子**:装载因子是哈希表中已存储元素数量与总槽位数的比值,它直接影响...

    线性表,链表,哈希表

    哈希表是一种基于数组的数据结构,通过使用哈希函数将键映射到数组中的位置,从而实现快速查找。哈希表的主要优势在于查找、插入和删除操作的平均时间复杂度都可以达到O(1)。在Java中,`Map`接口提供了哈希表的功能...

    利用C语言实现HashTable

    提供的`hashcode`函数基于ELF哈希算法,它将字符串转换为整数,通过位运算减少冲突。ELF哈希算法的特点是快速且散列效果良好。 `hashtable_put`函数首先计算键的哈希值,然后通过哈希值找到对应的数组索引。如果...

Global site tag (gtag.js) - Google Analytics