/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */ voidsiftDown(vector<int> &nums, int n, int i){ while (true) { // 判断节点 i, l, r 中值最大的节点,记为 ma int l = 2 * i + 1; int r = 2 * i + 2; int ma = i; if (l < n && nums[l] > nums[ma]) ma = l; if (r < n && nums[r] > nums[ma]) ma = r; // 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出 if (ma == i) { break; } // 交换两节点 swap(nums[i], nums[ma]); // 循环向下堆化 i = ma; } }
/* 堆排序 */ voidheapSort(vector<int> &nums){ // 建堆操作:堆化除叶节点以外的其他所有节点 for (int i = nums.size() / 2 - 1; i >= 0; --i) { siftDown(nums, nums.size(), i); } // 从堆中提取最大元素,循环 n-1 轮 for (int i = nums.size() - 1; i > 0; --i) { // 交换根节点与最右叶节点(交换首元素与尾元素) swap(nums[0], nums[i]); // 以根节点为起点,从顶至底进行堆化 siftDown(nums, i, 0); } }
defsift_down(nums: list[int], n: int, i: int): """堆的长度为 n ,从节点 i 开始,从顶至底堆化""" whileTrue: # 判断节点 i, l, r 中值最大的节点,记为 ma l = 2 * i + 1 r = 2 * i + 2 ma = i if l < n and nums[l] > nums[ma]: ma = l if r < n and nums[r] > nums[ma]: ma = r # 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出 if ma == i: break # 交换两节点 nums[i], nums[ma] = nums[ma], nums[i] # 循环向下堆化 i = ma
defheap_sort(nums: list[int]): """堆排序""" # 建堆操作:堆化除叶节点以外的其他所有节点 for i inrange(len(nums) // 2 - 1, -1, -1): sift_down(nums, len(nums), i) # 从堆中提取最大元素,循环 n-1 轮 for i inrange(len(nums) - 1, 0, -1): # 交换根节点与最右叶节点(交换首元素与尾元素) nums[0], nums[i] = nums[i], nums[0] # 以根节点为起点,从顶至底进行堆化 sift_down(nums, i, 0)
/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */ voidsiftDown(int[] nums, int n, int i) { while (true) { // 判断节点 i, l, r 中值最大的节点,记为 ma intl=2 * i + 1; intr=2 * i + 2; intma= i; if (l < n && nums[l] > nums[ma]) ma = l; if (r < n && nums[r] > nums[ma]) ma = r; // 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出 if (ma == i) break; // 交换两节点 inttemp= nums[i]; nums[i] = nums[ma]; nums[ma] = temp; // 循环向下堆化 i = ma; } }