数据结构:线性开型寻址散列实现(java)

散列函数:除法映射 f(k)=k%D

解决溢出:线性开型寻址

        线性开型寻址即是当发生冲突时,把元素存储到下一个可用的“桶”中。

初始化

       散列表使用数组实现,将数组全部初始化为-1,-1代表当前“桶”为空。usedLen字段代表以使用的数组长度,bucketsLen字段代表数组的长度,因为经常使用数组的长度,所以我专门使用一个字段表示数组的长度。

    private int[] buckets;
    private int usedLen;
    private int bucketsLen;

    public OpenAddressingHash(int bucketsLen) {
        this.bucketsLen = bucketsLen;
        usedLen = 0;
        buckets = new int[bucketsLen];

        //全部初始化为-1,-1代表空桶
        for (int i = 0; i < bucketsLen; i++) {
            buckets[i] = -1;
        }
    }

查找

       搜索时首先搜索起始同f(k),接着对表中后续桶进行搜索。直到发生以下情况:(1)找到了要搜索的元素;(2)到达一个空桶;(3)又回到f(k)桶。若发生后两种情况,则说明表中没有要搜索元素,返回-1。

    public int search(int value) {
        int loc = value % bucketsLen;
        while (buckets[loc] != value) {
            loc++;
            loc %= bucketsLen;

            if (buckets[loc] == -1 || loc == value % bucketsLen)
                return -1;
        }
        return loc;
    }

插入

        插入发生冲突时,使用线性开型寻址。当数组已满,则抛出ArrayIndexOutOfBoundsException错误。不要忘记usedLen+1。

    public void insert(int value) {
        //线性开型寻址
        if (usedLen < bucketsLen) {
            if (search(value) != -1) {
                return;
            }
            int loc = value % bucketsLen;
            while (buckets[loc] != -1) {
                loc++;
                loc %= bucketsLen;
            }
            buckets[loc] = value;
            usedLen++;
        } else {
            //表满溢出
            throw new ArrayIndexOutOfBoundsException();
        }
    }

删除

       删除时必须保证散列中存在该元素。因为使用的是线性开型寻址,所以在删除后需要逐个检查每个“桶”确定要移动的元素,直到到达一个“空桶”或到达删除操作所对应的“桶”。在删除后移动某个元素时,将其位置置为-1,并重新插入该元素。

    public void delete(int value) {
        int remainder = value % bucketsLen;
        int loc = search(value);
        if (loc != -1) {
            buckets[loc] = -1;
            usedLen --;
            loc++;
            loc %= bucketsLen;
            while (buckets[loc] != -1 && loc != remainder) {
                int num = buckets[loc];
                buckets[loc] = -1;
                insert(num);
                usedLen --;
                loc++;
                loc %= bucketsLen;
            }
        } else {
            throw new NoSuchElementException();
        }
    }

测试

        为方便测试,写了一个print()函数

    public void print() {
        for (int i = 0; i < bucketsLen; i++) {
            System.out.print(buckets[i] + " ");
        }
        System.out.println();
    }

        分别进行插入、搜索、删除测试。

public class OpenAddressingHashTest {
    public static void main(String args[]) {
        int[] testArray = {9, 34, 56, 67, 1, 32, 11, 9, 66};
        OpenAddressingHash openAddressingHash = new OpenAddressingHash(10);
        System.out.println("插入测试");
        //插入测试
        for (int i = 0; i < testArray.length; i++) {
            openAddressingHash.insert(testArray[i]);
            openAddressingHash.print();
        }

        //查找测试
        System.out.println("查找测试");
        System.out.println(openAddressingHash.search(56));
        openAddressingHash.print();
        System.out.println(openAddressingHash.search(1));
        openAddressingHash.print();

        //删除测试
        System.out.println("删除测试");
        openAddressingHash.delete(56);
        openAddressingHash.print();

    }
}

测试结果,结果无误。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值