直入主题!
1.堆
(二叉)堆是数组,可看成近似的完全二叉树。例如A[1..n]中,A[i]的父节点是A[i/2],左右孩子分别为A[2i],A[2i+1](假设都存在)。
于是可得父节点,左孩子,右孩子的下标:
Parent(i)
return i / 2Left(i)
return 2 * iRight(i)
return 2 * i + 1二叉堆的两种形式: 最大堆与最小堆。
最大堆:除了根以外的节点i都满足:
A[Parent(i)] >= A[i]
最小堆:除了根以外的节点i都满足:
A[Parent(i)] <= A[i]
2.维护堆的性质
运用Max-Heapify函数,对于每个节点i,找出它与它的左右孩子中最大的并交换。伪代码如下:
Max-Heapify(A, i) // 修改判断大小即可变为维护最小堆性质
l = Left(i) // 左孩子下标
r = Right(i) // 右孩子下标
if l <= A.heap-size and A[l] > A[i]
largest = l
else
largest = i
if r <= A.heap-size and A[r] > A[largest]
largest = r
if largest != i
exchange A[i] with A[largest]
Max-Heapify(A, largest) // 防止交换后largest节点不满足可以证明在数组只有根节点的一个子节点不满足堆的性质时,运用该函数能让数组变为最大(小)堆。
3.构建堆
首先引入一个性质:堆的叶的下标为n/2+1,n/2+2,...n。
根据这个性质可得:堆非叶下标为1,2,...n/2。
即前n/2个节点都有子节点。
因此在构建堆时,从n/2开始向上堆建。
Build-Max-Heap(A)
A.heap-size = A.length
for i=A.length/2 downto 2
Max-Heapify(A, i)对于每一个节点i,都满足子数组的根节点至多有一个子节点不满足堆的性质,因此用Max-Heapify函数能使得该子数组成为堆。
4.堆排序
最大堆中最大的节点一定为A[1],根据这一特性来对数组排序。
Heapsort(A)
Build-Max-Heap(A) // 构建最大堆
for i=A.length downto 2
exchange A[i] with A[1]
A.heap-size = A.heap-size - 1
Max-Heapify(A, 1)构建最大堆后,A[1]为最大值,将其与最后一项调换,并缩减堆的大小,前i-1项满足根节点的一个子节点不满足堆的性质,用Max-Heapify函数让其成为堆,依次循环即可对A排序。
(PS:用栈可实现从大到小排序)
5.优先队列
使用堆能使优先队列的一些操作变得简单。
找出队列最大关键字:
Heap-Maximum(A)
return A[1]找出并删除队列最大关键字:
Heap-Extract-Max(A)
if A.heapsize < 1
error"heap underflow"
max = A[1]
A[1] = A[A.heap-size]
A.heap-size = A.heap-size - 1
Max-Heapify(A, 1)
return max去掉最大值的方法为让A[1]变为A[A.heap-size],然后缩减堆大小并建堆。
将元素i的关键字增加到key:
Heap-Increase-Key(A, i, key)
if A[i] > key
error
A[i] = key
while i > 1 and A[i] > A[Parent(i)]
exchange A[i] with A[Parent(i)]
i = Parent(i)插入元素:
Max-Heap-Insert(A, key)
A.heap-size = A.heap-size + 1
A.[A.heap-size] = -∞
Heap-Inscrease-Key(A, A.heap-size, key)警告!!!以下为C++代码!!!!
堆排序:
#include<iostream>
using namespace std;
int a[100005] = {0}, n, size;
int parent(int i) //叫爸爸
{
return i / 2;
}
int left(int i) //左儿子
{
return i * 2;
}
int right(int i) //右儿子
{
return i * 2 + 1;
}
void Max_Heapify(int a[], int i) //让爸爸最大
{
int l = left(i);
int r = right(i);
int largest = 0;
if(l <= size && a[l] > a[i])
largest = l;
else
largest = i;
if(r <= size && a[r] > a[largest])
largest = r;
if(largest != i)
{
swap(a[i], a[largest]);
Max_Heapify(a, largest);
}
}
void Build_Max_Heap(int a[]) //使数组成为最大堆
{
for(int i = n / 2; i >= 1; i--)
Max_Heapify(a, i);
}
void Heapsort(int a[]) //堆排序,最大堆的根节点为堆的最大值
{
Build_Max_Heap(a);
for(int i = n; i >= 2; i--)
{
swap(a[1], a[i]);
size--;
Max_Heapify(a, 1);
}
}
int main()
{
cin>>n;
size = n;
for(int i = 1; i <= n; i++)
cin>>a[i];
Heapsort(a);
for(int i = 1; i <= n; i++)
cout<<a[i]<<" ";
return 0;
}优先队列:
#include<iostream>
#include<cmath>
using namespace std;
int a[100005] = {0}, n, size;
int parent(int i) //叫爸爸
{
return i / 2;
}
int left(int i) //左儿子
{
return i * 2;
}
int right(int i) //右儿子
{
return i * 2 + 1;
}
void Max_Heapify(int a[], int i) //让爸爸最大
{
int l = left(i);
int r = right(i);
int largest = 0;
if(l <= size && a[l] > a[i])
largest = l;
else
largest = i;
if(r <= size && a[r] > a[largest])
largest = r;
if(largest != i)
{
swap(a[i], a[largest]);
Max_Heapify(a, largest);
}
}
void Build_Max_Heap(int a[]) //使数组成为最大堆
{
for(int i = n / 2; i >= 1; i--)
Max_Heapify(a, i);
}
void Heapsort(int a[]) //堆排序,最大堆的根节点为堆的最大值
{
Build_Max_Heap(a);
for(int i = n; i >= 2; i--)
{
swap(a[1], a[i]);
size--;
Max_Heapify(a, 1);
}
}
int Heap_Maximum(int a[]) //返回堆最大值
{
return a[1];
}
int Heap_Extract_Max(int a[]) //返回堆最大值并删除
{
int max = a[1];
a[1] = a[size];
size--;
Max_Heapify(a, 1);
return max;
}
void Heap_Increase_Key(int a[], int i, int key) //让a[i]增加到key
{
if(a[i] > key)
cout<<"error"<<endl;
else
{
a[i] = key;
while(i > 1 && a[i] > a[parent(i)])
{
swap(a[i], a[parent(i)]);
i = parent(i);
}
}
}
int main()
{
cout<<"输入数组大小:";
cin>>n;
size = n;
cout<<"输入数组元素:";
for(int i = 1; i <= n; i++)
cin>>a[i];
Build_Max_Heap(a);
for(int j = 1, i = 1; i <= n; i++)
{
cout<<a[i]<<" ";
if(i == pow(2, j)-1)
{
cout<<endl;
j++;
}
}
cout<<endl<<"输入改变元素及值:";
int x, y;
cin>>x>>y;
size = n;
Heap_Increase_Key(a, x, y);
for(int j = 1, i = 1; i <= n; i++)
{
cout<<a[i]<<" ";
if(i == pow(2, j)-1)
{
cout<<endl;
j++;
}
}
cout<<endl<<"Max:"<<Heap_Maximum(a)<<endl;
int maxi = Heap_Extract_Max(a);
cout<<"Max:"<<maxi<<", Size:"<<size;
return 0;
}

京公网安备 11010502036488号