69 文心一言 VS 讯飞星火 VS chatgpt -- 算法导论6( 二 )


3.将堆顶元素(即 p 指向的元素)与结点 i 交换位置 。
4.调整堆 , 使得交换后的堆仍满足堆的性质 。具体来说 , 我们可以从 p 开始 , 依次向下调整堆 , 直到调整到叶子节点为止 。
由于使用二分查找的方法 , 每次查找都可以将查找范围缩小一半 , 因此 , 对于一个包含 n 个元素的堆 , 最多需要进行 logn 次查找 。而且 , 在调整堆的过程中 , 我们只需要对涉及到的元素进行交换和调整 , 因此 , 总的时间复杂度为 O(lgn) 。
因此 , 我们可以设计一个能够在 O(lgn) 时间内完成的 HEAP- 操作 , 具体实现如下:
void heap_delete(int arr[], int n, int i) {int p = 1, left = 2 * p, right = 2 * p + 1;while (left <= right) {if (left < right && arr[left] < arr[right]) {if (arr[left] > i) {swap(arr[i], arr[left]);p = left;}} else {if (arr[right] < i) {swap(arr[i], arr[right]);p = right;}}adjust_heap(arr, n, p);left = 2 * p, right = 2 * p + 1;}}
其中 , swap 函数用于交换两个元素 ,  函数用于调整堆 。在函数中 , 我们可以使用递归的方式 , 从 p 开始 , 依次向下调整堆 , 直到调整到叶子节点为止 。具体来说 , 我们可以依次对左右子树进行调整 , 如果左子树的深度小于右子树的深度 , 则将左子树作为当前节点的子树 , 否则将右子树作为当前节点的子树 。在调整子树的过程中 , 我们只需要对涉及到的元素进行交换和调整 , 直到子树满足堆的性质为止 。
通义千问:
可以采用双向链表来维护堆结构 , 同时利用堆的特性保证删除操作的时间复杂度为 O(lgn) 。
具体实现如下:
1.定义一个结点类 Node , 包含结点的值和指向左右子结点的指针 。
2.定义一个双向链表 Head , 表示堆的根结点 。将 Head 指向的结点标记为堆顶结点 。
3.在插入结点时 , 先将新结点插入到双向链表的末尾 , 然后进行向下调整 , 使新结点成为堆顶结点 。
4.在删除结点时 , 先将堆顶结点指向删除结点的右子结点 , 然后将删除结点的左子结点指向堆顶结点 , 最后进行向下调整 , 使堆保持堆的特性 。
代码如下:
class Node:def __init__(self, val):self.val = valself.left = Noneself.right = Noneclass Heap:def __init__(self):self.head = Nonedef heapify(self, node, i):largest = nodel = 2 * i + 1r = 2 * i + 2# 找到左右子结点 , 并比较大小if l < len(self) and self[l].val > largest.val:largest = self[l]if r < len(self) and self[r].val > largest.val:largest = self[r]# 如果当前结点大于最大结点 , 则交换位置 , 并进行向下调整if largest != node:self[largest.val, :].left = nodenode.left = self[largest, :]self[largest, :].right = nodenode.right = self[largest, :]# 如果左子结点存在 , 则进行向下调整if l < len(self) and self[l].val > node.val:self.heapify(self[l], l)# 如果右子结点存在 , 则进行向下调整if r < len(self) and self[r].val > node.val:self.heapify(self[r], r)def insert(self, val):new_node = Node(val)# 如果堆为空 , 则创建一个新的堆if not self.head:self.head = new_nodenew_node.left = new_node.right = Nonereturn# 将新结点插入到双向链表的末尾new_node.left = self.headself.head.right = new_node# 进行向下调整 , 使新结点成为堆顶结点self.heapify(new_node, 0)def delete(self, val):# 定位删除结点的位置i = self.search(val)# 如果删除结点不存在 , 则返回空if i == -1:return# 将堆顶结点指向删除结点的右子结点self.head.left = self[i].right# 将删除结点的左子结点指向堆顶结点self[i].left = self.head# 进行向下调整 , 使堆保持堆的特性self.heapify(self.head, 0)def search(self, val):# 遍历整个堆 , 查找是否存在该结点for i in range(len(self) - 1, -1, -1):if self[i].val == val:return ireturn -1