哈希表中的键有时会与自己发生冲突是否正常?

时间:2017-04-15 19:03:02

标签: java hashtable

这是我第二次参加Stack Overflow,所以请告诉我,如果我错过任何细节,抱歉,如果我的问题格式不正确,我不会经常使用这个网站。

我的问题是:当我运行我的代码时,它应该作为输出打印回来:

  • 填充的哈希表的百分比,

  • 总累积碰撞,

  • 冲突总数,

  • 将密钥插入哈希表时与之冲突的密钥的名称。

所有这些都很好,除非打印出与之碰撞的键的名称,有时它打印出与插入的键相同的名称,我不确定是否应该在哈希中发生是否可以?

/** 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);
        }

    }

}

出现问题的示例输出(输出实际上比此长):

------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

1 个答案:

答案 0 :(得分:1)

is it normal for the key to collide with itself 

是的,哈希冲突是正常的,当对一组随机大键进行散列时,实际上可能无法避免。证明可以是 - 哈希码为integer类型,最大值为(2^32)-1。但是,像HashMap / Hashtable这样的哈希表实现遵循冲突解决策略来处理此类事件。此处使用的策略称为单独链接,其中创建存储桶并具有某种具有相同索引的条目列表。如果您使用&#34; HashMap内部实施&#34;,您可以找到更多详细信息。

基本上,如果我们需要在碰撞的情况下检索值对象,则对hashCode()方法的调用将通过使用keys.equals()比较每个条目中的键来检索存储桶和遍历思想列表,直到它匹配为止。因此,在Java&#34;覆盖等于&#34;覆盖哈希码时有一个常见的说法。因为两个不相等的对象可能返回相同的哈希码但是当两个对象等于equals()时,它们必须具有相同的哈希码。