堆排序
两个条件
-
堆是完全二叉树
-
堆中父结点的值大于等于(或小于等于)子结点的值
数学关系
对于索引为i的父结点:
-
其父结点为(i-1)/2
-
其子结点分别为2i+1和2i+2
时间复杂度
nlogn
代码
void heapify(vector<int>& nums, int n, int i)
{
int l = 2 * i + 1, r = 2 * i + 2;
int max = i;
if (l < n && nums[l] > nums[max])
max = l;
if (r < n && nums[r] > nums[max])
max = r;
if (max != i)
{
swap(nums[max], nums[i]);
heapify(nums, n, max);
}
}
// 建立大根堆,从树的倒数第二层第一个结点开始
void buildHeap(vector<int>& nums, int n)
// 对每个结点进行 heapify 操作,然后向上走
{
int start = (n - 2) / 2;
for (int i = start; i >= 0; i--)
{
heapify(nums, n, i);
}
for (int i = 0; i < nums.size(); i++)
{
cout << nums[i] << " ";
}
cout << endl;
}
// 建立大根堆之后,每次交换最后一个结点和根结点(最大值),
// 对交换后的根结点继续进行 heapify (此时堆的最后一位是最大值,因此不用管他,n 变为 n-1)
void heapSort(vector<int>& nums, int n)
{
buildHeap(nums, n);
for (int i = 0; i < n; i++)
{
swap(nums[0], nums[n - i - 1]);
heapify(nums, n - i - 1, 0);
}
}
heapSort(A, A.size());
for (auto i : A)
{
cout << i << " ";
}
cout << endl;
浙公网安备 33010602011771号