Con trăn heapq
Heap là một cấu trúc cây đặc biệt trong đó mỗi nút cha nhỏ hơn hoặc bằng nút con của nó. Khi đó nó được gọi là Min Heap. Nếu mỗi nút cha lớn hơn hoặc bằng nút con của nó thì nó được gọi là max heap. Sẽ rất hữu ích khi triển khai các hàng đợi ưu tiên trong đó mục hàng đợi có trọng số cao hơn được ưu tiên hơn trong quá trình xử lý Show
Một cuộc thảo luận chi tiết về đống có sẵn trên trang web của chúng tôi ở đây. Vui lòng nghiên cứu nó trước nếu bạn chưa quen với cấu trúc dữ liệu heap. Trong chương này, chúng ta sẽ thấy việc triển khai cấu trúc dữ liệu heap bằng python Tạo một đốngMột đống được tạo bằng cách sử dụng thư viện có sẵn của python có tên là heapq. Thư viện này có các chức năng liên quan để thực hiện các thao tác khác nhau trên cấu trúc dữ liệu heap. Dưới đây là danh sách các chức năng này
Tạo một đốngMột đống được tạo bằng cách sử dụng danh sách các phần tử có chức năng heapify. Trong ví dụ dưới đây, chúng tôi cung cấp một danh sách các phần tử và hàm heapify sắp xếp lại các phần tử đưa phần tử nhỏ nhất lên vị trí đầu tiên Ví dụimport heapq H = [21,1,45,78,3,5] # Use heapify to rearrange the elements heapq.heapify(H) print(H) đầu raKhi đoạn mã trên được thực thi, nó tạo ra kết quả sau - [1, 3, 5, 78, 21, 45] Chèn vào đốngChèn một phần tử dữ liệu vào một đống luôn thêm phần tử vào chỉ mục cuối cùng. Nhưng bạn có thể áp dụng lại hàm heapify để đưa phần tử mới được thêm vào chỉ mục đầu tiên nếu nó có giá trị nhỏ nhất. Trong ví dụ dưới đây, chúng tôi chèn số 8 Ví dụimport heapq H = [21,1,45,78,3,5] # Covert to a heap heapq.heapify(H) print(H) # Add element heapq.heappush(H,8) print(H) đầu raKhi đoạn mã trên được thực thi, nó tạo ra kết quả sau - [1, 3, 5, 78, 21, 45] [1, 3, 5, 78, 21, 45, 8] Xóa khỏi đốngBạn có thể xóa phần tử ở chỉ mục đầu tiên bằng cách sử dụng chức năng này. Trong ví dụ dưới đây, hàm sẽ luôn xóa phần tử ở vị trí chỉ mục 1 Ví dụimport heapq H = [21,1,45,78,3,5] # Create the heap heapq.heapify(H) print(H) # Remove element from the heap heapq.heappop(H) print(H) đầu raKhi đoạn mã trên được thực thi, nó tạo ra kết quả sau - [1, 3, 5, 78, 21, 45] [3, 21, 5, 78, 45] Thay thế trong một đốngHàm thay thế heap luôn loại bỏ phần tử nhỏ nhất của heap và chèn phần tử mới đến vào một vị trí không cố định theo bất kỳ thứ tự nào Hàng đống và hàng đợi ưu tiên là những cấu trúc dữ liệu ít được biết đến nhưng hữu ích một cách đáng ngạc nhiên. Đối với nhiều vấn đề liên quan đến việc tìm kiếm phần tử tốt nhất trong tập dữ liệu, họ đưa ra giải pháp dễ sử dụng và hiệu quả cao. Mô-đun Python 6 là một phần của thư viện chuẩn. Nó thực hiện tất cả các hoạt động heap cấp thấp cũng như một số cách sử dụng phổ biến cấp cao cho heapA là một công cụ mạnh mẽ có thể giải quyết các vấn đề đa dạng như viết trình lập lịch trình email, tìm đường đi ngắn nhất trên bản đồ hoặc hợp nhất các tệp nhật ký. Lập trình chứa đầy các vấn đề tối ưu hóa, trong đó mục tiêu là tìm ra phần tử tốt nhất. Hàng đợi ưu tiên và các chức năng trong mô-đun 6 của Python thường có thể giúp ích cho việc đóTrong hướng dẫn này, bạn sẽ học
Hướng dẫn này dành cho Pythonistas, những người cảm thấy thoải mái với danh sách, ký tự, bộ và trình tạo và đang tìm kiếm các cấu trúc dữ liệu phức tạp hơn Bạn có thể làm theo các ví dụ trong hướng dẫn này bằng cách tải xuống mã nguồn từ liên kết bên dưới Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về mô-đun heapq Python trong hướng dẫn này đống là gì?Đống là cấu trúc dữ liệu cụ thể, trong khi hàng đợi ưu tiên là cấu trúc dữ liệu trừu tượng. Cấu trúc dữ liệu trừu tượng xác định giao diện, trong khi cấu trúc dữ liệu cụ thể xác định việc triển khai Heap thường được sử dụng để triển khai hàng đợi ưu tiên. Chúng là cấu trúc dữ liệu cụ thể phổ biến nhất để triển khai cấu trúc dữ liệu trừu tượng hàng đợi ưu tiên Cấu trúc dữ liệu cụ thể cũng xác định đảm bảo hiệu suất. Đảm bảo hiệu suất xác định mối quan hệ giữa kích thước của cấu trúc và thời gian thực hiện các hoạt động. Hiểu những đảm bảo đó cho phép bạn dự đoán chương trình sẽ mất bao nhiêu thời gian khi kích thước đầu vào của nó thay đổi Loại bỏ các quảng cáoCấu trúc dữ liệu, đống và hàng đợi ưu tiênCấu trúc dữ liệu trừu tượng chỉ định các hoạt động và mối quan hệ giữa chúng. Ví dụ, cấu trúc dữ liệu trừu tượng của hàng đợi ưu tiên hỗ trợ ba thao tác
Hàng đợi ưu tiên thường được sử dụng để tối ưu hóa việc thực thi tác vụ, trong đó mục tiêu là thực hiện tác vụ có mức độ ưu tiên cao nhất. Sau khi một nhiệm vụ được hoàn thành, mức độ ưu tiên của nó sẽ bị hạ xuống và nó được đưa trở lại hàng đợi Có hai quy ước khác nhau để xác định mức độ ưu tiên của một phần tử
Hai quy ước này tương đương nhau vì bạn luôn có thể đảo ngược thứ tự thực tế. Ví dụ: nếu các phần tử của bạn bao gồm các số, thì việc sử dụng số âm sẽ đảo ngược các quy ước xung quanh Mô-đun Python 6 sử dụng quy ước thứ hai, thường là quy ước phổ biến hơn trong hai quy ước. Theo quy ước này, phần tử nhỏ nhất có mức ưu tiên cao nhất. Điều này nghe có vẻ đáng ngạc nhiên, nhưng nó thường khá hữu ích. Trong các ví dụ thực tế mà bạn sẽ thấy sau này, quy ước này sẽ đơn giản hóa mã của bạnGhi chú. Mô-đun Python 6 và cấu trúc dữ liệu heap nói chung không được thiết kế để cho phép tìm bất kỳ phần tử nào ngoại trừ phần tử nhỏ nhất. Để truy xuất bất kỳ phần tử nào theo kích thước, tùy chọn tốt hơn là cây tìm kiếm nhị phânCấu trúc dữ liệu cụ thể thực hiện các hoạt động được xác định trong cấu trúc dữ liệu trừu tượng và chỉ định thêm các đảm bảo hiệu suất Việc triển khai heap của hàng đợi ưu tiên đảm bảo rằng cả hai phần tử đẩy (thêm) và bật (xóa) đều là hoạt động thời gian logarit. Điều này có nghĩa là thời gian cần thiết để thực hiện thao tác đẩy và bật tỷ lệ thuận với logarit cơ số 2 của số phần tử Logarit phát triển chậm. Logarit cơ số 2 của mười lăm là khoảng bốn, trong khi logarit cơ số 2 của một nghìn tỷ là khoảng bốn mươi. Điều này có nghĩa là nếu một thuật toán đủ nhanh trên mười lăm phần tử, thì nó sẽ chỉ chậm hơn mười lần trên một nghìn tỷ phần tử và có thể vẫn đủ nhanh Trong bất kỳ cuộc thảo luận nào về hiệu suất, lưu ý lớn nhất là những cân nhắc trừu tượng này ít có ý nghĩa hơn so với việc đo lường thực sự một chương trình cụ thể và tìm hiểu xem các nút thắt cổ chai nằm ở đâu. Đảm bảo hiệu suất chung vẫn rất quan trọng để đưa ra các dự đoán hữu ích về hành vi của chương trình, nhưng những dự đoán đó cần được xác nhận Thực hiện đốngHeap cài đặt hàng đợi ưu tiên dưới dạng cây nhị phân hoàn chỉnh. Trong cây nhị phân, mỗi nút sẽ có nhiều nhất hai nút con. Trong một cây nhị phân hoàn chỉnh, tất cả các mức trừ mức sâu nhất có thể luôn đầy. Nếu mức sâu nhất không đầy đủ, thì nó sẽ có các nút càng xa về bên trái càng tốt Thuộc tính đầy đủ có nghĩa là độ sâu của cây là logarit cơ số 2 của số phần tử, được làm tròn lên. Đây là một ví dụ về cây nhị phân hoàn chỉnh Trong ví dụ cụ thể này, tất cả các cấp đã hoàn thành. Mỗi nút ngoại trừ nút sâu nhất có đúng hai nút con. Có tổng cộng bảy nút ở ba cấp độ. Ba là logarit cơ số 2 của bảy, được làm tròn lên Nút duy nhất ở cấp cơ sở được gọi là nút gốc. Có vẻ lạ khi gọi nút ở trên cùng của cây là gốc, nhưng đây là quy ước phổ biến trong lập trình và khoa học máy tính Hiệu suất đảm bảo trong một đống phụ thuộc vào cách các phần tử thấm lên và xuống cây. Kết quả thực tế của việc này là số phép so sánh trong một đống là logarit cơ số 2 của kích thước của cây Ghi chú. So sánh đôi khi liên quan đến việc gọi mã do người dùng xác định bằng cách sử dụng 1. Gọi các phương thức do người dùng định nghĩa trong Python là một thao tác tương đối chậm so với các thao tác khác được thực hiện trong một đống, vì vậy đây thường sẽ là nút cổ chaiTrong cây heap, giá trị trong một nút luôn nhỏ hơn cả hai nút con của nó. Đây được gọi là thuộc tính heap. Điều này khác với cây tìm kiếm nhị phân, trong đó chỉ có nút bên trái sẽ nhỏ hơn giá trị của nút cha của nó Các thuật toán cho cả push và popping dựa vào việc tạm thời vi phạm thuộc tính heap, sau đó sửa thuộc tính heap thông qua so sánh và thay thế lên hoặc xuống một nhánh Ví dụ: để đẩy một phần tử lên một đống, Python sẽ thêm nút mới vào vị trí mở tiếp theo. Nếu lớp dưới cùng không đầy, thì nút đó sẽ được thêm vào vị trí mở tiếp theo ở dưới cùng. Mặt khác, một cấp độ mới được tạo và sau đó phần tử được thêm vào lớp dưới cùng mới Khi nút được thêm vào, Python sẽ so sánh nút đó với nút gốc của nó. Nếu thuộc tính heap bị vi phạm, thì nút và cha của nó sẽ được chuyển đổi và quá trình kiểm tra bắt đầu lại tại cha. Điều này tiếp tục cho đến khi thuộc tính heap được giữ hoặc đã đạt đến gốc Tương tự, khi popping phần tử nhỏ nhất, Python biết rằng, do thuộc tính heap, phần tử nằm ở gốc của cây. Nó thay thế phần tử bằng phần tử cuối cùng ở lớp sâu nhất và sau đó kiểm tra xem thuộc tính heap có bị vi phạm ở nhánh không Loại bỏ các quảng cáoCông dụng của hàng đợi ưu tiênHàng đợi ưu tiên và heap dưới dạng triển khai hàng đợi ưu tiên, rất hữu ích cho các chương trình liên quan đến việc tìm kiếm một phần tử cực trị theo một cách nào đó. Ví dụ: bạn có thể sử dụng hàng đợi ưu tiên cho bất kỳ tác vụ nào sau đây
Một nhiệm vụ khác mà bạn có thể sử dụng hàng đợi ưu tiên là lên lịch gửi email. Hãy tưởng tượng một hệ thống có nhiều loại email, mỗi loại cần được gửi ở một tần suất nhất định. Một loại email cần được gửi đi cứ sau mười lăm phút và một loại khác cần được gửi sau mỗi bốn mươi phút Người lên lịch có thể thêm cả hai loại email vào hàng đợi với dấu thời gian cho biết khi nào cần gửi email tiếp theo. Sau đó, bộ lập lịch có thể xem phần tử có dấu thời gian nhỏ nhất—cho biết phần tử đó sẽ được gửi tiếp theo—và tính toán thời gian ngủ trước khi gửi Khi bộ lập lịch thức dậy, nó sẽ xử lý email có liên quan, đưa email ra khỏi hàng đợi ưu tiên, tính toán dấu thời gian tiếp theo và đưa email trở lại hàng đợi ở đúng vị trí Đống dưới dạng Danh sách trong Mô-đun >>> import heapq >>> a = [3, 5, 1, 2, 6, 8, 7] >>> heapq.heapify(a) >>> a [1, 2, 3, 5, 6, 8, 7] 6 của PythonMặc dù bạn đã thấy heap được mô tả trước đó là một cái cây, nhưng điều quan trọng cần nhớ là nó là một cây nhị phân hoàn chỉnh. Tính đầy đủ có nghĩa là luôn có thể biết có bao nhiêu phần tử ở mỗi lớp ngoại trừ lớp cuối cùng. Do đó, đống có thể được triển khai dưới dạng danh sách. Đây là những gì mô-đun Python 6 làmCó ba quy tắc xác định mối quan hệ giữa phần tử tại chỉ số 4 và các phần tử xung quanh nó
Ghi chú. Ký hiệu 8 là toán tử chia số nguyên. Nó luôn làm tròn xuống một số nguyênCác quy tắc trên cho bạn biết cách trực quan hóa danh sách dưới dạng cây nhị phân hoàn chỉnh. Hãy nhớ rằng một phần tử luôn có phần tử cha, nhưng một số phần tử không có phần tử con. Nếu 9 nằm ngoài cuối danh sách, thì phần tử không có phần tử con nào. Nếu 5 là một chỉ mục hợp lệ nhưng 6 thì không, thì phần tử chỉ có một conThuộc tính heap có nghĩa là nếu 2 là một đống thì phần sau sẽ không bao giờ là 3
Nó có thể tăng 4 nếu bất kỳ chỉ số nào vượt quá độ dài của danh sách, nhưng nó sẽ không bao giờ là 3Nói cách khác, một phần tử phải luôn nhỏ hơn các phần tử ở hai lần chỉ số của nó cộng một và hai lần chỉ số của nó cộng hai Đây là hình ảnh của một danh sách thỏa mãn thuộc tính heap Các mũi tên đi từ phần tử 4 đến phần tử 5 và 6. Ví dụ: phần tử đầu tiên trong danh sách Python có chỉ số 9, vì vậy hai mũi tên của nó chỉ vào các chỉ số 0 và 1. Lưu ý cách các mũi tên luôn đi từ giá trị nhỏ hơn đến giá trị lớn hơn. Đây là cách bạn có thể kiểm tra xem danh sách có thỏa mãn thuộc tính heap khôngHoạt động cơ bảnMô-đun Python 6 thực hiện các thao tác heap trên danh sách. Không giống như nhiều mô-đun khác, nó không định nghĩa một lớp tùy chỉnh. Mô-đun Python 6 có các chức năng hoạt động trực tiếp trên danh sáchThông thường, như trong ví dụ email ở trên, các phần tử sẽ được chèn từng phần tử một vào heap, bắt đầu bằng một heap trống. Tuy nhiên, nếu đã có một danh sách các phần tử cần phải là một đống, thì mô-đun Python 6 bao gồm 5 để biến một danh sách thành một đống hợp lệĐoạn mã sau sử dụng 5 để biến 7 thành một đống>>>
Bạn có thể kiểm tra xem mặc dù 8 đứng sau 9 nhưng danh sách 7 vẫn tuân theo thuộc tính heap. Ví dụ: 1, là 2, nhỏ hơn 3, là 8Như bạn có thể thấy, 5 sửa đổi danh sách tại chỗ nhưng không sắp xếp nó. Một đống không cần phải được sắp xếp để đáp ứng thuộc tính heap. Tuy nhiên, vì mọi danh sách được sắp xếp đều thỏa mãn thuộc tính heap, nên việc chạy 5 trên danh sách được sắp xếp sẽ không thay đổi thứ tự của các phần tử trong danh sáchCác hoạt động cơ bản khác trong mô-đun Python 6 giả định rằng danh sách đã là một đống. Thật hữu ích khi lưu ý rằng một danh sách trống hoặc danh sách có độ dài sẽ luôn là một đốngVì gốc của cây là phần tử đầu tiên, nên bạn không cần một chức năng chuyên dụng để đọc phần tử nhỏ nhất một cách không phá hủy. Phần tử đầu tiên, 8, sẽ luôn là phần tử nhỏ nhấtĐể bật phần tử nhỏ nhất trong khi vẫn giữ nguyên thuộc tính heap, mô-đun Python 6 định nghĩa 0Đây là cách sử dụng 0 để bật một phần tử>>>
Hàm trả về phần tử đầu tiên, 0 và giữ nguyên thuộc tính heap trên 7. Ví dụ: 4 là 5 và 6 là 7Mô-đun Python 6 cũng bao gồm 9 để đẩy một phần tử vào heap trong khi vẫn giữ nguyên thuộc tính heapVí dụ sau đây cho thấy việc đẩy một giá trị lên một đống >>>
Sau khi đẩy 0 vào đống, bạn bật ba phần tử từ nó. Vì 1 và 2 đã ở trong đống và nhỏ hơn 0 nên chúng được xuất hiện đầu tiênMô-đun Python 6 cũng định nghĩa thêm hai thao tác
Chúng hữu ích trong một số thuật toán vì chúng hiệu quả hơn so với thực hiện hai thao tác riêng biệt Loại bỏ các quảng cáoHoạt động cấp caoVì các hàng đợi ưu tiên thường được sử dụng để hợp nhất các chuỗi đã sắp xếp, nên mô-đun 6 của Python có một chức năng làm sẵn, 2, để sử dụng các đống để hợp nhất một số lần lặp. 2 giả sử các iterable đầu vào của nó đã được sắp xếp và trả về một iterator, không phải danh sáchNhư một ví dụ về việc sử dụng 2, đây là cách triển khai bộ lập lịch email được mô tả trước đó
Đầu vào cho 2 trong ví dụ này là. Giá trị trả về được gán cho biến 6 cũng là một trình vòng lặp vô hạn. Trình lặp này sẽ mang lại các email được gửi theo thứ tự dấu thời gian trong tương laiĐể gỡ lỗi và xác nhận rằng mã được hợp nhất chính xác, bạn có thể in mười email đầu tiên sẽ được gửi >>>
Lưu ý cách 7 được lên lịch mỗi 8 phút, 9 được lên lịch mỗi 0 và các email được xen kẽ hợp lý để chúng được sắp xếp theo thứ tự dấu thời gian của chúng 2 không đọc tất cả dữ liệu đầu vào, mà thay vào đó, nó hoạt động linh hoạt. Mặc dù cả hai đầu vào đều là trình lặp vô hạn, việc in mười mục đầu tiên sẽ kết thúc nhanh chóngTheo cách tương tự, khi được sử dụng để hợp nhất các chuỗi đã sắp xếp như các dòng tệp nhật ký được sắp xếp theo dấu thời gian, ngay cả khi nhật ký lớn, điều này sẽ chiếm một lượng bộ nhớ hợp lý đống vấn đề có thể giải quyếtNhư bạn đã thấy ở trên, đống rất tốt cho việc hợp nhất dần dần các chuỗi đã sắp xếp. Hai ứng dụng cho đống mà bạn đã xem xét là lên lịch các tác vụ định kỳ và hợp nhất các tệp nhật ký. Tuy nhiên còn rất nhiều ứng dụng khác Đống cũng có thể giúp xác định n thứ trên cùng hoặc n thứ dưới cùng. Mô-đun Python 6 có các chức năng cấp cao thực hiện hành vi nàyVí dụ: mã này lấy dữ liệu đầu vào là thời gian từ trận chung kết 100 mét nữ tại Thế vận hội Mùa hè 2016 và in ra những người đoạt huy chương hoặc ba người về đích hàng đầu >>>
Mã này sử dụng 3 từ mô-đun Python 6. 3 trả về các phần tử nhỏ nhất trong một lần lặp và chấp nhận ba đối số
Ở đây, hàm 8 tách dòng theo khoảng trắng, lấy phần tử cuối cùng và chuyển đổi nó thành một. Điều này có nghĩa là mã sẽ sắp xếp các dòng theo thời gian chạy và trả về ba dòng có thời gian chạy nhỏ nhất. Những thứ này tương ứng với ba vận động viên chạy nhanh nhất, mang lại cho bạn huy chương vàng, bạc và đồngMô-đun 6 của Python cũng bao gồm 01, có các tham số tương tự và trả về các phần tử lớn nhất. Điều này sẽ hữu ích nếu bạn muốn giành huy chương từ cuộc thi ném lao, trong đó mục tiêu là ném lao càng xa càng tốtCách xác định vấn đềMột đống, với tư cách là một triển khai của hàng đợi ưu tiên, là một công cụ tốt để giải quyết các vấn đề liên quan đến các điểm cực đoan, chẳng hạn như nhiều nhất hoặc ít nhất của một số liệu nhất định Có những từ khác chỉ ra một đống có thể hữu ích
Bất cứ khi nào một tuyên bố vấn đề chỉ ra rằng bạn đang tìm kiếm một yếu tố cực đoan nào đó, bạn nên suy nghĩ xem hàng đợi ưu tiên có hữu ích hay không Đôi khi hàng đợi ưu tiên sẽ chỉ là một phần của giải pháp và phần còn lại sẽ là một số biến thể của lập trình động. Đây là trường hợp của ví dụ đầy đủ mà bạn sẽ thấy trong phần tiếp theo. Lập trình động và hàng đợi ưu tiên thường hữu ích cùng nhau Loại bỏ các quảng cáoVí dụ. Tìm đường dẫnVí dụ sau đây đóng vai trò là trường hợp sử dụng thực tế cho mô-đun Python 6. Ví dụ này sẽ sử dụng một thuật toán cổ điển, là một phần của nó, yêu cầu một đống. Bạn có thể tải xuống mã nguồn được sử dụng trong các ví dụ bằng cách nhấp vào liên kết bên dướiLấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về mô-đun heapq Python trong hướng dẫn này Hãy tưởng tượng một robot cần điều hướng một mê cung hai chiều. Robot cần đi từ điểm xuất phát, nằm ở góc trên cùng bên trái, đến điểm đến ở góc dưới cùng bên phải. Robot có một bản đồ mê cung trong bộ nhớ, vì vậy nó có thể vạch ra toàn bộ đường đi trước khi khởi hành Mục tiêu là để robot hoàn thành mê cung càng nhanh càng tốt Thuật toán của chúng tôi là một biến thể của thuật toán Dijkstra. Có ba cấu trúc dữ liệu được lưu giữ và cập nhật trong suốt thuật toán
Ở mỗi bước, bạn thực hiện tối đa bốn hành động
Các bước được chạy trong một vòng lặp cho đến khi đích được thêm vào bộ 05. Khi điểm đến nằm trong tập hợp 05, bạn đã hoàn thành. Đầu ra của thuật toán là đường dẫn 03 đến đích, bây giờ là đường dẫn ngắn nhất có thể là ____6_______05Mã cấp cao nhấtBây giờ bạn đã hiểu thuật toán, đã đến lúc viết mã để triển khai nó. Trước khi tự triển khai thuật toán, bạn nên viết một số mã hỗ trợ Trước tiên, bạn cần đến mô-đun Python 6
Bạn sẽ sử dụng các hàm từ mô-đun 6 của Python để duy trì một đống giúp bạn tìm vị trí có đường đi ngắn nhất đã biết ở mỗi lần lặpBước tiếp theo là xác định bản đồ dưới dạng một biến trong mã
Bản đồ là một bản đồ hiển thị khu vực mà robot có thể di chuyển cũng như bất kỳ chướng ngại vật nào Mặc dù một kịch bản thực tế hơn sẽ yêu cầu bạn đọc bản đồ từ một tệp, nhưng vì mục đích giảng dạy, việc xác định một biến trong mã bằng cách sử dụng bản đồ đơn giản này sẽ dễ dàng hơn. Mã này sẽ hoạt động trên mọi bản đồ nhưng sẽ dễ hiểu và dễ gỡ lỗi hơn trên bản đồ đơn giản Bản đồ này được tối ưu hóa để dễ hiểu đối với người đọc mã của con người. Dấu chấm (_______6_______20) đủ sáng để trông có vẻ trống rỗng, nhưng nó có lợi thế là hiển thị kích thước của khu vực được phép. Các vị trí 21 đánh dấu các chướng ngại vật mà robot không thể đi quaLoại bỏ các quảng cáoMã hỗ trợChức năng đầu tiên sẽ chuyển đổi bản đồ thành thứ gì đó dễ phân tích cú pháp hơn trong mã. 22 lấy bản đồ và phân tích nó
Hàm lấy một bản đồ và trả về một bộ gồm ba phần tử
Điều này cho phép phần còn lại của mã hoạt động trên các cấu trúc dữ liệu được thiết kế cho máy tính, không dành cho khả năng quét trực quan của con người Danh sách 23 có thể được lập chỉ mục theo tọa độ 27. Biểu thức 28 trả về giá trị của vị trí là một trong hai ký tự
Điều này sẽ hữu ích khi bạn muốn tìm những vị trí mà robot có thể chiếm giữ Hàm 31 tính toán xem một vị trí 27 đã cho có hợp lệ hay không 0Hàm này nhận hai đối số
Để hợp lệ, một vị trí phải nằm trong ranh giới của bản đồ và không phải là chướng ngại vật Hàm kiểm tra xem 36 có hợp lệ hay không bằng cách kiểm tra độ dài của danh sách 23. Hàm tiếp theo sẽ kiểm tra xem 38 có hợp lệ hay không bằng cách đảm bảo rằng nó nằm bên trong 39. Cuối cùng, bây giờ bạn đã biết cả hai tọa độ đều nằm trong bản đồ, mã sẽ kiểm tra xem chúng có phải là chướng ngại vật hay không bằng cách nhìn vào ký tự ở vị trí này và so sánh ký tự đó với 30Một công cụ trợ giúp hữu ích khác là 41, tìm tất cả các lân cận của một vị trí 1Hàm trả về tất cả các vị trí hợp lệ xung quanh vị trí hiện tại 41 cẩn thận để tránh xác định một vị trí là hàng xóm của chính nó, nhưng nó cho phép các hàng xóm chéo. Đây là lý do tại sao ít nhất một trong số 43 và 44 không được bằng 0, nhưng cả hai khác không cũng không saoHàm trợ giúp cuối cùng là 45, tìm các đường dẫn ngắn hơn 2 45 mang lại các vị trí mà đường dẫn có ____6_______47 là bước cuối cùng của nó ngắn hơn đường dẫn đã biết hiện tại 45 có ba tham số
Giả định là tất cả các phần tử trong 50 có thể đạt được trong một bước từ 47Hàm 45 kiểm tra xem việc sử dụng 47 làm bước cuối cùng có tạo ra một đường dẫn tốt hơn cho từng vị trí hay không. Nếu không biết đường dẫn đến một vị trí, thì bất kỳ đường dẫn nào cũng ngắn hơn. Nếu có một đường dẫn đã biết, thì bạn chỉ tạo ra đường dẫn mới nếu độ dài của nó ngắn hơn. Để làm cho API của 45 dễ sử dụng hơn, một phần của 58 cũng là con đường ngắn hơnTất cả các hàm của trình trợ giúp được viết là các hàm thuần túy, nghĩa là chúng không sửa đổi bất kỳ cấu trúc dữ liệu nào và chỉ trả về các giá trị. Điều này giúp dễ dàng tuân theo thuật toán cốt lõi, thuật toán này thực hiện tất cả các cập nhật cấu trúc dữ liệu Loại bỏ các quảng cáoMã thuật toán cốt lõiTóm lại, bạn đang tìm kiếm con đường ngắn nhất giữa điểm xuất phát và điểm đến Bạn giữ ba mẩu dữ liệu
Một vị trí ở 05 nếu bạn có thể chắc chắn rằng con đường ngắn nhất đã biết là con đường ngắn nhất có thể. Nếu điểm đến nằm trong tập hợp 05, thì đường đi ngắn nhất đã biết đến đích chắc chắn là đường đi ngắn nhất có thể và bạn có thể trả về đường đi nàyĐống 07 được sắp xếp theo độ dài của đường đi ngắn nhất đã biết và được quản lý với sự trợ giúp của các hàm trong mô-đun 6 của PythonỞ mỗi bước, bạn nhìn vào ứng viên có đường đi ngắn nhất đã biết. Đây là nơi đống đang được bật lên với 0. Không có con đường nào ngắn hơn đến ứng cử viên này—tất cả các con đường khác đều đi qua một số nút khác trong 07 và tất cả những con đường này đều dài hơn. Do đó, ứng viên hiện tại có thể được đánh dấu là 05Sau đó, bạn xem xét tất cả các hàng xóm chưa được thăm và nếu việc đi qua nút hiện tại là một cải tiến, thì bạn thêm chúng vào đống 07 bằng cách sử dụng 9Hàm 71 thực hiện thuật toán này 3 71 nhận một 73 dưới dạng một chuỗi và trả về đường dẫn từ điểm gốc đến đích dưới dạng danh sách các vị tríChức năng này hơi dài và phức tạp, vì vậy hãy xem qua từng chút một
Chia chức năng thành các phần riêng biệt cho phép bạn hiểu từng phần một Mã trực quanNếu thuật toán thực sự được sử dụng bởi rô bốt, thì rô bốt có thể sẽ hoạt động tốt hơn với danh sách các vị trí mà nó sẽ đi qua. Tuy nhiên, để làm cho kết quả trông đẹp hơn với con người, sẽ tốt hơn nếu trực quan hóa chúng 85 vẽ một con đường trên bản đồ 4Hàm lấy các tham số là 86 và 73. Nó trả về một bản đồ mới với đường dẫn được biểu thị bằng ký hiệu at ( 88)Chạy mãCuối cùng, bạn cần gọi các chức năng. Điều này có thể được thực hiện từ Đoạn mã sau sẽ chạy thuật toán và hiển thị một đầu ra đẹp >>> 5Trước tiên, bạn có được con đường ngắn nhất từ _______6_______71. Sau đó, bạn chuyển nó cho 85 để hiển thị bản đồ với đường dẫn được đánh dấu trên đó. Cuối cùng, bạn 91 ánh xạ ra chuẩn đầu raCon đường di chuyển một bước về bên phải, sau đó một vài bước chéo về phía dưới cùng bên phải, rồi thêm vài bước nữa về bên phải và cuối cùng nó kết thúc bằng một bước chéo về phía dưới cùng bên phải Chúc mừng. Bạn đã giải quyết một vấn đề bằng cách sử dụng mô-đun Python 6Những loại vấn đề tìm đường này, có thể giải quyết được bằng cách kết hợp lập trình động và hàng đợi ưu tiên, thường gặp trong các cuộc phỏng vấn xin việc và thử thách lập trình. Ví dụ: Advent of Code 2019 bao gồm một vấn đề có thể được giải quyết bằng các kỹ thuật được mô tả tại đây Loại bỏ các quảng cáoPhần kết luậnBây giờ bạn đã biết cấu trúc dữ liệu hàng đợi ưu tiên và heap là gì và loại vấn đề nào chúng hữu ích trong việc giải quyết. Bạn đã học cách sử dụng mô-đun Python 6 để sử dụng danh sách Python dưới dạng đống. Bạn cũng đã học cách sử dụng các thao tác cấp cao trong mô-đun 6 của Python, chẳng hạn như 2, sử dụng một đống trong nội bộTrong hướng dẫn này, bạn đã học cách
Với kiến thức của bạn về heaps và mô-đun 6 của Python, giờ đây bạn có thể giải nhiều bài toán trong đó lời giải phụ thuộc vào việc tìm phần tử nhỏ nhất hoặc lớn nhất. Để làm theo các ví dụ bạn đã thấy trong hướng dẫn này, bạn có thể tải xuống mã nguồn từ liên kết bên dướiLấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về mô-đun heapq Python trong hướng dẫn này Đánh dấu là đã hoàn thành 🐍 Thủ thuật Python 💌 Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python Gửi cho tôi thủ thuật Python » Giới thiệu về Moshe Zadka Moshe đã sử dụng Python từ năm 1998. Anh ấy đã đóng góp cho CPython và là thành viên sáng lập của dự án Twisted. Anh ấy đã dạy Python ở nhiều địa điểm khác nhau từ năm 2002 » Thông tin thêm về MosheMỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là Aldren David Geir Arne Joanna Gia-cốp Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » Chuyên gia Kỹ năng Python trong thế giới thực Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » Bạn nghĩ sao? Đánh giá bài viết này Tweet Chia sẻ Chia sẻ EmailBài học số 1 hoặc điều yêu thích mà bạn đã học được là gì? Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi |