构建min heap的Python实现

时间:2015-04-20 18:39:58

标签: python algorithm python-3.x data-structures heap

以下代码填充最小堆有什么问题? bubble_up方法不起作用,它会使索引超出范围错误。

 def __init__(self):
    self.heap = []
    self.heap_size = 0

 def bubble_up(self, i):
    print(self.heap)
    while i // 2 > 0:
        if self.heap[i] < self.heap[i // 2]:
            tmp = self.heap[i // 2 - 1]
            self.heap[i] = self.heap[i // 2]
            self.heap[i // 2] = tmp
        print(self.heap)
        i = i // 2


def insert(self, data):
    self.heap.append(data)
    self.heap_size = self.heap_size + 1
    self.bubble_up(self.heap_size)

if __name__ == "__main__":
    min_heap = MinHeap()
    min_heap.insert(5)
    min_heap.insert(4)
    min_heap.insert(3)
    min_heap.insert(2)
    min_heap.insert(6)

2 个答案:

答案 0 :(得分:1)

def insert(self, data):
    self.heap.append(data)
    self.heap_size = self.heap_size + 1
    self.bubble_up(self.heap_size)

您附加数据,增加heap_size,然后使用新的(增加的)堆大小调用bubble_up

在那里,你检查:

 if self.heap[i] < self.heap[i // 2]:

其中i是堆大小。您不能这样做,如果堆中有3个元素,则无法访问heap[3]。它不存在,您唯一有效的索引是0, 1, 2

可能的解决方法(未经测试):使用bubble_up致电heap_size - 1

请注意,if中的代码看起来并不正确:

tmp = self.heap[i // 2 - 1]        # why -1 here? shouldn't this be heap[i]?
self.heap[i] = self.heap[i // 2]   # shouldn't this be the other way around? why no -1 here?
self.heap[i // 2] = tmp            # why no -1 here? shouldn't this be heap[i]?

此外,如果条件为假,您可以将i // 2置于此条件中并退出循环。

答案 1 :(得分:0)

当前发布的答案准确地描述了为什么你会出现一个outofbounds错误,但如果你只是用bubble_up()调用heap_size-1,它将无法正确维护堆。请注意bubble_up()中代码的以下部分:

while i // 2 > 0:

您当前的while循环语句不会将堆根的直接子节点与根节点进行比较。假设你插入3然后1。当您插入1时,bubble_up()将无法正确地将插入的1与3交换,因为由于i//2 == 0 i == 11而无法在您的while语句中运行交换例程是插入的while i > 0: parent = i // 2 <put your comparison & swap method here> i = parent 位置。我将此块切换为以下内容:

{
   "html_attributions" : [],
   "next_page_token" : "CqQCGwEAAI5PpCTJI6Qoa1CD9iA4EpJha6t0gMlZ3I3DpOIVgE1BUYh5NNI0lXRuvAltI8RhOilTNJggXsR3TEP2C6hoIsibEWZXnZClbEcZzes7LGqJuQ0heJWipe7RNbxq8S8zuao1HWfECs11i44WO0Luv-4bYx5GlCEj6Wl07LitkzwG4u0e4FyIHogyaShky5Awd44ZyOcqKzy7wYBr7p37j6A6PMdR7zn7cMWQKiVolfHQbFZerVJ3JJ5MiKSshocG189wPKjqJzSACE6W19LmZ7TIMB9qm7jQANNQStrsq7rYAWIBQ-UqJ_6Hv9jv1xL7eRQ9bkyR17u7xPZWfeCU69u_PQmGvuvSWNJDvNUuoI-uwLc_RhgTZp26kyzMlXwYHRIQXy13ridwzgvlBU8ez_y-WBoUcBN7UvN8Q8iuDyS_LjXEWmT_sIk",
   "results" : [
      {
         "geometry" : {
            "location" : {
               "lat" : 28.615572,
               "lng" : 77.3468
            },
            "viewport" : {
               "northeast" : {
                  "lat" : 28.6169209802915,
                  "lng" : 77.34814898029151
               },
               "southwest" : {
                  "lat" : 28.6142230197085,
                  "lng" : 77.34545101970849
               }
            }
         },
         "icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
         "id" : "dea8496f678dc1f01381a85298e37a0905a3ca11",
         "name" : "Malabar Junction Restaurant",
         "opening_hours" : {
            "open_now" : true,
            "weekday_text" : []
         },
         "photos" : [
            {
               "height" : 746,
               "html_attributions" : [
                  "\u003ca href=\"https://maps.google.com/maps/contrib/117230637789134827076/photos\"\u003eSwati\u003c/a\u003e"
               ],
               "photo_reference" : "CmRaAAAArbpjr1fjNp2Fc4ww8Vkgrzzzt5aHEvACzEZFa-XCJU3Fw2JqFLSDo64jlFWwDZwdYaFP_cIgdqI37TJ25mVB2W_rtoTv_aI0LJGgnh_P4-UF7u45ZvqdM-bE4ljYD2yyEhDjv-4AWC5AKcE713GL1qAsGhQjAN2oS1KWv52f8XsjEK3Pmnv53w",
               "width" : 750
            }
         ],
         "place_id" : "ChIJx6qqqj3lDDkRcBw22oTfWgk",
         "reference" : "CmRRAAAAZBpNfAiO2G_y57bLoFTSM28MG4xUi-VAg3kJgV2ZzksdhpzySwxdPNdPP1paEIE46i70oxgLHliUcEjxalukNEyhN85J-ryRbXVVMkg4Tz-MGBGhgVur7SV5b4IFePnfEhABXu9pHswL4Up5w-k9td94GhSDs13DRQVxPOpI8iWqUbLyd_WJUg",
         "scope" : "GOOGLE",
         "types" : [ "restaurant", "food", "point_of_interest", "establishment" ],
         "vicinity" : "62, 8, Rani Jhansi Marg, Block 10, Sector 10, Noida"
      }
   ],
   "status" : "OK"
}