Xác định: Hashset là gì?


420

Hashset Cấu trúc dữ liệu C # Hashset được giới thiệu trong .NET Framework 3.5. Một danh sách đầy đủ của các thành viên được thực hiện có thể được tìm thấy tại trang MSDN Hashset .

  1. Nó được sử dụng ở đâu?
  2. Tại sao bạn muốn sử dụng nó?



Nó sử dụng một hashtable trong nội bộ. nếu bạn có triển khai hashtable tốt (ví dụ: Từ điển <T>), bạn có thể tự thực hiện Hashset một cách dễ dàng.
Raz Megrelidze

Câu trả lời:


614
    1. A HashSetgiữ một tập hợp các đối tượng, nhưng theo cách nó cho phép bạn dễ dàng và nhanh chóng xác định xem một đối tượng đã có trong tập hợp hay chưa. Nó làm như vậy bằng cách quản lý nội bộ một mảng và lưu trữ đối tượng bằng cách sử dụng một chỉ mục được tính từ mã băm của đối tượng. Hãy xem ở đây

    2. HashSetlà một bộ sưu tập không có thứ tự chứa các yếu tố độc đáo. Nó có các hoạt động thu thập tiêu chuẩn Thêm, Xóa, Chứa, nhưng vì nó sử dụng triển khai dựa trên hàm băm, nên các hoạt động này là O (1). (Trái ngược với Danh sách chẳng hạn, đó là O (n) cho Chứa và Xóa.) HashSetCũng cung cấp các thao tác thiết lập tiêu chuẩn như liên kết , giao nhauchênh lệch đối xứng . Hãy xem ở đây

  1. Có nhiều cách triển khai khác nhau của Bộ. Một số thực hiện thao tác chèn và tra cứu siêu nhanh bằng cách băm các phần tử. Tuy nhiên, điều đó có nghĩa là thứ tự các yếu tố được thêm vào bị mất. Các triển khai khác bảo toàn thứ tự được thêm vào với chi phí thời gian chạy chậm hơn.

Các HashSetlớp trong C # đi cho cách tiếp cận đầu tiên, do đó không giữ gìn trật tự của các yếu tố. Nó nhanh hơn nhiều so với thông thường List. Một số điểm chuẩn cơ bản cho thấy Hashset nhanh hơn khi xử lý các loại chính (int, double, bool, v.v.). Nó nhanh hơn rất nhiều khi làm việc với các đối tượng lớp. Vì vậy, điểm đó là Hashset nhanh.

Điều hấp dẫn duy nhất HashSetlà không có quyền truy cập của các chỉ số. Để truy cập các phần tử, bạn có thể sử dụng một điều tra viên hoặc sử dụng hàm tích hợp để chuyển đổi HashSetthành một Listvà lặp qua đó. Hãy xem ở đây


13
Hai thứ, hashset và tương tự là .NET, không phải C #. Ngoài ra Hashset không bảo toàn trật tự. Hãy thử thêm và xóa các mục khỏi bộ băm, bạn sẽ biết nếu bạn lặp lại sau này ..
nawfal

13

A HashSetcó cấu trúc bên trong (hàm băm), trong đó các mục có thể được tìm kiếm và xác định nhanh chóng. Nhược điểm là lặp đi lặp lại qua mộtHashSet (hoặc nhận một mục theo chỉ mục) là khá chậm.

Vậy tại sao ai đó muốn có thể biết nếu một mục đã tồn tại trong một tập hợp?

Một tình huống trong đó HashSethữu ích là nhận được các giá trị riêng biệt từ danh sách nơi các bản sao có thể tồn tại. Khi một mục được thêm vào, HashSetnó sẽ nhanh chóng xác định xem mục đó có tồn tại không ( Containstoán tử).

Lợi thế khác của HashSetlà những hoạt động Set: IntersectWith, IsSubsetOf, IsSupersetOf, Overlaps, SymmetricExceptWith, UnionWith.

Nếu bạn quen thuộc với ngôn ngữ ràng buộc đối tượng thì bạn sẽ xác định các thao tác thiết lập này. Bạn cũng sẽ thấy rằng đó là một bước gần hơn để triển khai UML thực thi.


20
Re: nhược điểm. Không, lặp qua Hashset là hoàn toàn nhanh. Thứ hai, không thể có được một mục theo chỉ mục. Trong thực tế, các yếu tố được lưu trữ không có thứ tự.
Nigel Touch

@Nigel Chạm. Lặp lại là nhanh nếu bạn không quan tâm đến chỉ mục (thứ tự mà chúng đã được thêm vào). Tuy nhiên, nếu bạn quan tâm đến chỉ mục thì chỉ mục phải được lưu trữ với mỗi khóa băm và do đó nó có thể khá chậm vì danh sách phải được tìm kiếm kỹ lưỡng để lấy đúng mục. Hành vi này rất khác với một danh sách trong đó các mục được lập chỉ mục theo thứ tự mà chúng được thêm vào.
k rey

Nó có ý nghĩa tại sao nó sẽ nhanh, bởi vì không có hai hàm băm nào giống nhau. Kích hoạt truy vấn để tận dụng cách tiếp cận "ngắn mạch", nhanh chóng loại trừ các tiêu chí nhất định.
Chef_Code

8

Nói một cách đơn giản và không tiết lộ bí mật nhà bếp: một bộ nói chung, là một bộ sưu tập không chứa các yếu tố trùng lặp và các yếu tố của chúng không theo thứ tự cụ thể. Vì vậy, A HashSet<T>tương tự như chung List<T>, nhưng được tối ưu hóa để tra cứu nhanh (thông qua hashtables, như tên ngụ ý) với chi phí mất đơn hàng.


1
Nhưng một Hashset <T> có thể lưu trữ hai đối tượng có cùng dữ liệu, như hai lớp Sản phẩm mà mỗi lớp có cùng thuộc tính với cùng một nội dung không?
Johan Herstad

Tôi đoán chúng ta sẽ không bao giờ biết
Denny

@JohanHerstad Giả sử EqualityComparer cho lớp của bạn quan tâm đến các thuộc tính đó hoặc bạn xây dựng Hashset bằng IEqualityComparer quan tâm đến các thuộc tính đó, tôi không hiểu tại sao nó lại không. Các tài liệu cho HashSet làm cho nó rõ ràng rằng nó dựa vào một hay khác để xác định tính độc đáo.
Bacon Bits

2

Từ góc độ ứng dụng, nếu chỉ cần tránh trùng lặp thì đó HashSetlà thứ bạn đang tìm kiếm vì nó Tra cứu, Chèn và Xóa độ phức tạp là O (1) - không đổi . Điều này có nghĩa là không quan trọng việc có bao nhiêu phần tử HashSetsẽ mất cùng một khoảng thời gian để kiểm tra xem có phần tử đó hay không, cộng với việc bạn chèn các phần tử vào O (1) cũng làm cho nó hoàn hảo cho loại điều này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.