简体   繁体   English

哈希表中的键有时会相互冲突是否正常?

[英]Is it normal for keys in a hashtable to sometimes collide with themselves?

This my 2nd time on Stack Overflow so please tell me if I am missing any details and sorry if my question is not that properly formatted, I'm not used this site constantly. 这是我第二次使用Stack Overflow,所以请告诉我是否遗漏了任何详细信息,如果问题的格式不正确,对不起,我不会一直使用此网站。

My question is: When I run my code it's supposed to print back as an output: 我的问题是:运行代码时,它应该作为输出打印回:

  • the percentage of the hash-table that is filled, 填充的哈希表的百分比,

  • the total accumulated collisions, 累计碰撞总数,

  • the total number of collisions, and 碰撞总数,以及

  • the name of keys that are being collided with when inserting keys into the hash-table. 将键插入哈希表时要与之冲突的键的名称。

All of which comes out fine except when printing out the names of the keys that are being collided with, sometimes it prints out the same name of the key being inserted, and I am not sure if that's supposed to happen in a hash-table or not? 除了打印出与之冲突的键的名称时,所有其他方法都可以正常工作,有时会打印出与插入键相同的名称,并且我不确定这是否应该在哈希表或不?

/** Container class for a key-value pair */

   class KVpair<Key, E> {
   private Key k;
   private E e;

  /** Constructors */
  KVpair()
    { k = null; e = null; }
  KVpair(Key kval, E eval)
    { k = kval; e = eval; }

  /** Data member access functions */
  public Key key() { return k; }
  public E value() { return e; }
 }


public class HashTable<Key extends Comparable<? super Key>, E> {

private int M;
private KVpair<Key, E>[] HT;
private int collisionSum = 0;

private int h(Key key) {
    HashFunction hf = new HashFunction();
    return hf.sfold((String) key, M);
}

private int p(Key key, int slot) {
    return slot;
}

@SuppressWarnings("unchecked") // Generic array allocation
HashTable(int m) {
    M = m;
    HT = (KVpair<Key, E>[]) new KVpair[M];
}

/** Insert record r with key k into HT */
void hashInsert(Key k, E r) {
    int home; // Home position for r
    int pos = home = h(k); // Initial position
    int AccumulatedSum = 0;
    for (int i = 1; HT[pos] != null; i++) {
        collisionSum++;
        AccumulatedSum++;
        if (HT[pos].key().compareTo(k) != 0 )
            System.out.println("Collided with key " + HT[pos].key());
        pos = (home + p(k, i)) % M; // Next probe slot
        assert HT[pos].key().compareTo(k) != 0 : "Duplicates not allowed";
    }
    HT[pos] = new KVpair<Key, E>(k, r); // Insert R
    System.out.printf("Accumulated collisions: %d\n", AccumulatedSum);
    System.out.printf("Total number of  Collisions %d\n", collisionSum);
}

/** Search in hash table HT for the record with key k */
E hashSearch(Key k) {
    int home; // Home position for k
    int pos = home = h(k); // Initial position
    for (int i = 1; (HT[pos] != null) && (HT[pos].key().compareTo(k) != 0); i++) {
        pos = (home + p(k, i)) % M; // Next probe position
        if (i == M) {
            return null;
        }
        System.out.println(pos);
    }

    return HT[pos].value(); // Found it
}

}


import java.io.*;
import java.math.*;

  // This is the hashFunction that will be used in the hashtable
  // for linear probing of indexes when collisions happen. 
   //where s is the String key being passed and M is the size of the hashTable 

    public class HashFunction
{

     int sfold(String s, int M) {

     int intLength = s.length() / 4;
     int sum = 0;
     for (int j = 0; j < intLength; j++) {
       char c[] = s.substring(j*4,(j*4)+4).toCharArray();
    int mult = 1;
    for (int k = 0; k < c.length; k++) {
        sum += c[k] * mult;
        mult *= 256;
      }
  }
     char c[] = s.substring(intLength * 4).toCharArray();
     int mult = 1;
     for (int k = 0; k < c.length; k++) {
        sum += c[k] * mult;
        mult *= 256;
  }
    return(Math.abs(sum) % M);
  }
    int h(String x, int M) {
    char ch[];
    ch = x.toCharArray();
    int xlength = x.length(); 
    int i, sum;
    for (sum=0, i=0; i < xlength; i++)
         sum += ch[i];
    return sum % M;
}
   int h(int x) {
    return(x % 16);
  }

}


import java.util.Arrays;
import java.util.Random;

public class randHashTableDriver {

    public static void main(String[] args) {

        int htLength = 128; // HashTable Size
        HashTable<String, String> hashT = new HashTable<>(htLength);
        HashTable<String, String> hashT2= new HashTable<>(htLength);
        fillHashTable(hashT, htLength, 0.4);
        fillHashTable(hashT2, htLength, 0.6);

    }

    // Generates a String array filled with words of 8 letters in length with no
    // duplicates
    static String[] randomWordGen(int wordCount) {
        int wordLength = 8;
        String[] words = new String[wordCount];
        Arrays.fill(words, "");
        Random r = new Random();
        for (int i = 0; i < wordCount; i++) {
            String s = "";
            for (int t = 0; t < wordLength; t++) {
                char c = (char) (r.nextInt(26) + 65);
                s += c;
            }
            if (Arrays.asList(words).contains(s)) {
                i--;
                continue;
            }
            words[i] += s;
        }
        return words;
    }

    // Creates the HashTable and Fills it with indexes until it reaches the
    // Percent specified
    static void fillHashTable(HashTable<String, String> h, int size, double fillPercentage ) {
        int indexes = (int) Math.ceil( size * fillPercentage);
        String[] words = randomWordGen(indexes);
        System.out.println("\n\n------Filling HashTable------");
        for (int i = 0; i < indexes; i++) {
            h.hashInsert(words[i], words[i]);
            System.out.printf("\nInserting Word: %s , FillPercentage: %.2f\n", words[i], ((i+1d) /size) * 100);
        }

    }

}

Example output of where the problem occurs (output is actually longer than this): 发生问题的位置的示例输出(输出实际上比这更长):

------Filling HashTable------
Accumulated collisions: 0
Total number of  Collisions 0

Inserting Word: KPUWLEYG , FillPercentage: 0.78
Accumulated collisions: 0
Total number of  Collisions 0

Inserting Word: CVJLHZTS , FillPercentage: 1.56
Accumulated collisions: 0
Total number of  Collisions 0

Inserting Word: PHTMMRDF , FillPercentage: 2.34
Collided with key PHTMMRDF
Accumulated collisions: 1
Total number of  Collisions 1

Inserting Word: LBHTQOZT , FillPercentage: 3.13
Accumulated collisions: 0
Total number of  Collisions 1

Inserting Word: JJIRZFEU , FillPercentage: 3.91
Accumulated collisions: 0
Total number of  Collisions 1

Inserting Word: ETWYECDW , FillPercentage: 4.69
Accumulated collisions: 0
Total number of  Collisions 1

Inserting Word: PEKVFYWK , FillPercentage: 5.47
Collided with key PHTMMRDF
Collided with key LBHTQOZT
Accumulated collisions: 2
Total number of  Collisions 3

Inserting Word: LSRKQZWI , FillPercentage: 6.25
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: QVVHNKKY , FillPercentage: 7.03
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: AWNKDWPU , FillPercentage: 7.81
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: BCLQXGGZ , FillPercentage: 8.59
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: NWCLTWVW , FillPercentage: 9.38
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: EZMHLCRT , FillPercentage: 10.16
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: AKOREOMM , FillPercentage: 10.94
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: TFFDJHDM , FillPercentage: 11.72
Accumulated collisions: 0
Total number of  Collisions 3

Inserting Word: CVLWLOMC , FillPercentage: 12.50
Collided with key PEKVFYWK
Accumulated collisions: 1
Total number of  Collisions 4

Inserting Word: JHTDLBBU , FillPercentage: 13.28
Accumulated collisions: 0
Total number of  Collisions 4

Inserting Word: DSQRNEFA , FillPercentage: 14.06
Accumulated collisions: 0
Total number of  Collisions 4

Inserting Word: FOBTANHC , FillPercentage: 14.84
Collided with key QVVHNKKY
Collided with key TFFDJHDM
Collided with key PHTMMRDF
Collided with key LBHTQOZT
Collided with key LSRKQZWI
Collided with key BCLQXGGZ
Accumulated collisions: 6
Total number of  Collisions 10

Inserting Word: MLJVRHMQ , FillPercentage: 15.63
Collided with key MLJVRHMQ
Accumulated collisions: 1
Total number of  Collisions 11
is it normal for the key to collide with itself 

Yes, Hash collision is normal and perhaps practically not avoidable when hashing a random large set of keys. 是的,散列冲突是正常的,在散列随机的大型键集时实际上是无法避免的。 A proof could be - hashcode is of integer type with the max value of (2^32)-1 . 证明可以是-哈希码是integer类型,最大值为(2^32)-1 However, the hash table implementations like HashMap/Hashtable follow collision resolution strategy to handle such events. 但是,像HashMap / Hashtable这样的哈希表实现遵循冲突解决策略来处理此类事件。 The strategy used here is called separate chaining where a bucket is created and has some sort of list of entries with the same index. 此处使用的策略称为单独链接,其中创建了存储桶,并具有某种具有相同索引的条目列表。 If you google with "HashMap intenal implementation", you can find more details. 如果您使用“ HashMap内部实施”来搜索Google,则可以找到更多详细信息。

Basically, if we need to retrieve value object in case of collision, a call to hashCode() method will retrieve bucket and traverse thought list by comparing keys in each entries using keys.equals() until it matches. 基本上,如果需要在发生冲突的情况下检索值对象,则对hashCode()方法的调用将通过使用keys.equals()比较每个条目中的键直到匹配,来检索存储桶并遍历思想列表。 Thus there is a common saying in Java "Override hashcode when you override equals" because two unequal objects may return the same hashcode but When two objects are equal by equals(), they must have the same hashcode. 因此,在Java中有一个俗语:“当您覆盖equals时,请覆盖哈希码”,因为两个不相等的对象可能返回相同的哈希码,但是当两个对象相等时,它们必须具有相同的哈希码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM