数据结构-Java实现散列表

概念

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

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

散列表

本文使用除留取余hash算法,使用链地址法处理地址冲突,在java语言中实现散列表的数据接口

节点数据结构

package com.billJiang.hashtable;

/**
 * Created by billJiang on 2016/11/30.
 * hashtable 节点 可能发生碰撞
 */
public class Entry<T> {
    int key;
    T item;
    Entry<T> next;

    public Entry(int key,T item,Entry<T> next){
        this.key=key;
        this.item=item;
        this.next=next;
    }
}

实现代码

package com.billJiang.hashtable;

import java.util.Arrays;

/**
 * Created by billJiang on 2016/11/30.
 */
public class HashTable<T> {
    private static final int INITIAL_SIZE=3;
    private static final float LOAD_FACTOR=0.75f;
    private  Entry<T>[] table;

    private int size=0;
    private int use=0;

    public HashTable() {
        table = new Entry[INITIAL_SIZE];
    }

    public void put(int key,T item){
        int index=hash(key);
        if(table[index]==null){
            table[index]=new Entry(-1,null,null);
        }
        Entry e=table[index];
        //未存过值
        if(e.next==null){
            Entry entry=new Entry(key,item,null);
            e.next=entry;
            size++;
            use++;
            if(use>=table.length*LOAD_FACTOR){
                resize();
            }
        }else{
            //已经存在值,替换
            for(e=e.next;e!=null;e=e.next){
                if(e.key==key){
                    e.item=item;
                    return;
                }
            }
            //追加
            Entry temp=table[index].next;
            Entry entry=new Entry(key,item,temp);
            table[index].next=entry;
            size++;
        }

    }

    public void remove(int key){
        int index=hash(key);
        Entry e=table[index];
        Entry pre=table[index];
        for(e=e.next;e!=null;e=e.next){
            if(e.key==key){
                pre.next=e.next;
                size--;
                 //TODO 24页缺少以下两行代码
                if (pre.key == -1 && e.next == null)
                    use--;
                break;
            }
            pre=e;
        }

    }

    public T get(int key){
       int index=hash(key);
        Entry e=table[index];
        for(e=e.next;e!=null;e=e.next){
            if(e.key==key){
                return (T) e.item;
            }
        }
        return null;
    }

    public int size(){
      return this.size;
    }

    public int getLength(){
       return table.length;
    }

    private int hash(int key){
       return key%table.length;
    }

    private void resize(){
      Entry[] oldTable=table;
        table=new Entry[table.length*2];
        use=0;
        for(int i=0;i<oldTable.length;i++){
            if(oldTable[i]!=null&&oldTable[i].next!=null){
                Entry e= oldTable[i];
                Entry next=e.next;
                while(e.next!=null){
                    int index=hash(next.key);
                    if(table[index]==null){
                        table[index]=new Entry(-1,null,null);
                        use++;
                    }
                    Entry temp=table[index].next;
                    table[index].next=new Entry(next.key,next.item,temp);
                    e=next;
                }
            }
        }

    }
}

测试代码

package com.billJiang.hashtable;

/**
 * Created by billJiang on 2016/11/30.
 */
public class HashTableTest {

    public static void main(String[] args) {
        HashTable<String> table=new HashTable<String>();
        table.put(1,"A");
        table.put(2,"B");
        table.put(3,"C");
        table.put(4,"D");

        table.put(5,"Hello world");

        table.remove(1);

    }
}

散列表的特点

  • 访问速度很快
  • 需要额外的空间
  • 无序
  • 可能发生碰撞

散列表经常用于缓存和快速查找。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值