2012-01-16 34 views
43

Tôi đang cố tạo một vùng heap với một biến vị ngữ sắp xếp tùy chỉnh. Vì các giá trị đi vào nó là kiểu 'do người dùng định nghĩa', tôi không thể sửa đổi biến vị ngữ so sánh được tích hợp của chúng.heapq với biến vị ngữ tùy chỉnh

Có cách nào để làm điều gì đó như:

h = heapq.heapify([...], key=my_lt_pred) 
h = heapq.heappush(h, key=my_lt_pred) 

Hoặc thậm chí tốt hơn, tôi có thể quấn các chức năng heapq trong container của riêng tôi vì vậy tôi không cần phải tiếp tục đi qua các vị ngữ.

+1

có thể trùng lặp của http://stackoverflow.com/questions/679731/min-heap-in-python –

+0

bản sao có thể có của [Làm thế nào để làm cho heapq đánh giá heap off của một thuộc tính cụ thể?] (Http: // stackoverflow .com/questions/3954530/how-to-make-heapq-đánh giá-the-heap-off-of-a-cụ thể-thuộc tính) –

Trả lời

58

Theo heapq documentation, cách để tùy chỉnh thứ tự vùng heap là có mỗi phần tử trên heap là một bộ tuple, với phần tử tuple đầu tiên là phần tử chấp nhận so sánh Python bình thường.

Các chức năng trong mô-đun heapq hơi cồng kềnh (vì chúng không hướng đối tượng) và luôn yêu cầu đối tượng heap (danh sách được heapified) của chúng tôi được truyền một cách rõ ràng làm thông số đầu tiên. Chúng ta có thể giết hai con chim bằng một viên đá bằng cách tạo ra một lớp bao bọc rất đơn giản cho phép chúng ta chỉ định một hàm key, và trình bày vùng heap như một đối tượng.

Lớp dưới đây giữ một danh sách nội bộ, trong đó mỗi phần tử là một tuple, thành viên đầu tiên trong số đó là một chìa khóa, tính tại thời điểm chèn yếu tố sử dụng tham số key, thông qua tại Heap instantiation:

# -*- coding: utf-8 -*- 
import heapq 

class MyHeap(object): 
    def __init__(self, initial=None, key=lambda x:x): 
     self.key = key 
     if initial: 
      self._data = [(key(item), item) for item in initial] 
      heapq.heapify(self._data) 
     else: 
      self._data = [] 

    def push(self, item): 
     heapq.heappush(self._data, (self.key(item), item)) 

    def pop(self): 
     return heapq.heappop(self._data)[1] 
+0

Rất đẹp! Bạn thậm chí có thể đi xa hơn và sử dụng bộ ba (self.key (item), id, item), trong đó id có thể là một số nguyên được xử lý như một thuộc tính lớp và tăng lên sau mỗi lần đẩy. Bằng cách đó, bạn tránh được ngoại lệ khi khóa (item1) = key (item2). Bởi vì chìa khóa sẽ là duy nhất. – zeycus

+1

Tôi thực sự đã cố gắng để đẩy điều này (hoặc một cái gì đó dựa trên điều này) vào stdlib Python, và đề nghị đã bị từ chối. – jsbueno

+0

đáng tiếc, phù hợp với phong cách hướng đối tượng của hầu hết các tính năng của Python và đối số chính cung cấp thêm sự linh hoạt. – zeycus

6

heapq documentation gợi ý rằng các phần tử heap có thể là bộ dữ liệu trong đó phần tử đầu tiên là ưu tiên và xác định thứ tự sắp xếp. Tuy nhiên,

Tùy thuộc vào câu hỏi của bạn, tài liệu bao gồm discussion with sample code về cách có thể triển khai các hàm bao bọc heapq riêng của chúng để xử lý các vấn đề về ổn định sắp xếp và các phần tử có mức độ ưu tiên ngang nhau (trong số các vấn đề khác).

Tóm lại, giải pháp của họ là có mỗi phần tử trong heapq là một phần ba với mức độ ưu tiên, số lượng mục nhập và phần tử được chèn vào. Số lượng mục nhập đảm bảo rằng các phần tử có cùng mức độ ưu tiên được sắp xếp theo thứ tự chúng được thêm vào heapq.

+0

Đây là giải pháp chính xác, cả heappush và heappushpop hoạt động trực tiếp với bộ dữ liệu – daisy

1

Hạn chế với cả hai câu trả lời là chúng không cho phép các mối quan hệ được coi là quan hệ. Trong lần đầu tiên, các mối quan hệ bị phá vỡ bằng cách so sánh các mục, trong mối quan hệ thứ hai bằng cách so sánh thứ tự đầu vào. Nó nhanh hơn chỉ để cho quan hệ là quan hệ, và nếu có rất nhiều trong số họ nó có thể tạo ra một sự khác biệt lớn. Dựa trên các tài liệu trên và trên tài liệu, nó không rõ ràng nếu điều này có thể đạt được trong heapq. Nó có vẻ lạ rằng heapq không chấp nhận một chìa khóa, trong khi chức năng bắt nguồn từ nó trong cùng một mô-đun làm.
P.S .: Nếu bạn theo liên kết trong nhận xét đầu tiên ("có thể trùng lặp ..."), có một đề xuất khác về định nghĩa le giống như một giải pháp.

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