2011-10-28 40 views
6

Tôi đã tạo cấu trúc dữ liệu "Tọa độ" tùy chỉnh xác định vị trí của một đối tượng theo một hệ thống nhất định.Tôi làm cách nào để tạo mã băm cho cấu trúc dữ liệu tùy chỉnh?

Một phối hợp được quy định như sau:

public class Coordinate 
{ 
    public int X; 
    public int Y; 
    private int face; 
    public int Face 
    { 
     get { return face; } 
     set 
     { 
      if (value >= 6 | value < 0) 
       throw new Exception("Invalid face number"); 
      else 
       face = value; 
     } 
    } 
    private int shell; 
    public int Shell 
    { 
     get { return shell; } 
     set 
     { 
      if (value < 0) 
       throw new Exception("No negative shell value allowed"); 
      else 
       shell = value; 
     } 
    } 

    public Coordinate(int face, int x, int y, int shell) 
    { 
     this.X = x; 
     this.Y = y; 
     this.face = face; 
     this.shell = shell; 
    } 

    public static Coordinate operator +(Coordinate a, Coordinate b) 
    { 
     return new Coordinate(a.Face + b.Face, a.X + b.X, a.Y + b.Y, a.Shell + b.Shell); 
    } 

    public override bool Equals(object obj) 
    { 
     Coordinate other = (obj as Coordinate); 
     if (other == null) 
      return false; 
     else 
      return (Face == other.Face && Shell == other.Shell && X == other.X && Y == other.Y); 
    } 
} 

Hoặc, để tóm tắt, nó chứa một int Face (0-5), một int X, int Y, và int Shell. X, Y và Shell đều bị ràng buộc bên dưới ở mức 0 (bao gồm).

Tôi không có chút kinh nghiệm nào về mã băm. Tôi cần so sánh chúng để xem chúng có bình đẳng không. Tôi đã thử điều này:

private const int MULTIPLIER = 89; 

[...] 

int hashCode = 1; 
hashCode = MULTIPLIER * hashCode + obj.X.GetHashCode(); 
hashCode = MULTIPLIER * hashCode + obj.Y.GetHashCode(); 
hashCode = MULTIPLIER * hashCode + obj.Face.GetHashCode(); 
hashCode = MULTIPLIER * hashCode + obj.Shell.GetHashCode(); 
return hashCode; 

Tắt thứ mà tôi tìm thấy trong khi Googling. Nhưng khi tôi cố gắng biên dịch mã với phương pháp này, tôi khá chắc chắn nó chạy vào va chạm, vì nó không bao giờ kết thúc xây dựng. Có lẽ đi vào tất cả các loại lộn xộn vòng nghĩ rằng một loạt các tọa độ là như nhau hoặc somesuch.

Tôi xin lỗi câu hỏi này là khá tiểu học, nhưng vì một lý do nào đó tôi bị bối rối. Tôi chỉ đang tìm lời khuyên về cách viết mã băm này để nó không va chạm.

+2

Không có vấn đề gì nếu mã băm đồng bộ. Tốt hơn là không nên va chạm, nhưng không cần thiết (và toán học cũng không thể). – Jon

+0

http://msdn.microsoft.com/en-us/library/system.object.gethashcode%28v=vs.71%29.aspx - "Các lớp có nguồn gốc phải ghi đè GetHashCode bằng cách triển khai trả về mã băm duy nhất. " –

+1

@MattFenwick Do nguyên tắc pigeonhole, không có điều gì như là một mã băm duy nhất cho hầu hết các loại.* Bài viết đó hơi không chính xác. Họ đã xóa dòng đó trong các phiên bản thành công. * - 'int.GetHashCode()' có lẽ là duy nhất cho mỗi số mặc dù. –

Trả lời

11

Nếu tốt này không phải là cách tốt nhất, nó có thể là một cách tiếp cận tốt, đủ:

public override int GetHashCode() 
{ 
    return string.Format("{0}-{1}-{2}-{3}", X, Y, Face, Shell).GetHashCode(); 
} 

Cập nhật: Hãy xem bài viết này: http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

+0

Điều này có vẻ thực sự tốt, cảm ơn. Tôi đã cố gắng nhân mỗi thành phần với 100000, 10000, 1000 và 1 trước đây để có được điều này, nhưng điều này là sạch hơn và có thể mở rộng. –

+0

Vâng, nó vẫn không xây dựng ... Tôi sẽ giữ hashcode này và làm một số thử nghiệm đơn vị để xem nếu tôi đang làm cái gì khác sai. –

+0

Tôi nên nói "nó vẫn bị kẹt", không phải "không xây dựng". Không có lỗi trình biên dịch. Trò chơi chỉ bị kẹt trong một vòng lặp sử dụng mã băm. –

2

Về cơ bản, khi viết hashcode chức năng, bạn cần đảm bảo rằng:

  • bạn không có mã băm cũ (nghĩa là trạng thái của đối tượng không nên thay đổi sau một hashcode đã được tạo ra, chẳng hạn rằng hashcode sẽ thay đổi nếu tái sinh)
  • đối tượng với giá trị tương đương trả lại hashcodes cùng
  • cùng một đối tượng luôn luôn trả về hashcode cùng (nếu nó không được sửa đổi) - xác định

Ngoài ra, nó là tuyệt vời, nhưng không cần thiết, nếu:

  • hashcodes của bạn được phân tán đều trên giá trị có thể (nguồn: Wikipedia)

Bạn không cần đảm bảo rằng các đối tượng khác nhau trả lại mã băm khác nhau. Nó chỉ cau mày vì nó có thể làm giảm hiệu suất của những thứ như Hashtables (nếu bạn có rất nhiều va chạm).

Tuy nhiên, nếu bạn vẫn muốn hàm băm của mình trả về các giá trị duy nhất, thì bạn muốn biết về perfect hashing.

Các vấn đề liên quan