本文内容和图片转载https://www.jianshu.com/p/0d383d294a80
堆
堆(二叉堆)可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示(普通的一般的二叉树通常用链表作为基本容器表示),每一个结点对应数组中的一个元素。
二叉堆一般分为两种:最大堆和最小堆。
最大堆:
最大堆中的最大元素值出现在根结点(堆顶)
堆中每个父节点的元素值都大于等于其孩子结点(如果存在)
最小堆:
最小堆中的最小元素值出现在根结点(堆顶)
堆中每个父节点的元素值都小于等于其孩子结点(如果存在)
堆排序
是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
堆排序的平均时间复杂度为 Ο(nlogn)。
算法步骤
1、创建一个堆 H[0……n-1];
2、把堆首(最大值)和堆尾互换;
3、把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
4、重复步骤 2,直到堆的尺寸为 1。
排序动画过程解释
1、首先,将所有的数字存储在堆中
2、按大顶堆构建堆,其中大顶堆的一个特性是数据将被从大到小取出,将取出的数字按照相反的顺序进行排列,数字就完成了排序
3、在这里数字 5 先入堆
4、数字 2 入堆
5、数字 7 入堆, 7 此时是最后一个节点,与最后一个非叶子节点(也就是数字 5 )进行比较,由于 7 大于 5 ,所以 7 和 5 交互
6、按照上述的操作将所有数字入堆,然后从左到右,从上到下进行调整,构造出大顶堆
7、入堆完成之后,将堆顶元素取出,将末尾元素置于堆顶,重新调整结构,使其满足堆定义
8、堆顶元素数字 7 取出,末尾元素数字 4 置于堆顶,为了维护好大顶堆的定义,最后一个非叶子节点数字 5 与 4 比较,而后交换两个数字的位置
9、反复执行调整+交换步骤,直到整个序列有序
代码实现
template<typename Item>
class MaxHeap
{
private: Item* data;
int count;
int capacity;
void shiftUp(int k)
{
while( k>1 && data[k/2] < data[k])
{
swap(data[k/2],data[k]);
k /= 2;
}
}
void shiftDnow(int k)
{
while(2*k < count) //当前k节点有子节点
{
int j = 2*k; //在此论循环中,data[k]和data[j]交换位置
if( j+1 <= count && data[j+1]>data[j])
j += 1;
if(data[k] >= data[j])
break;
swap(data[k],data[j]);
k=j;
}
}
public:
MaxHeap(int capacity)
{
data = new Item[capacity +1];
count = 0;
this->capacity = capacity;
}
// 构造函数, 通过一个给定数组创建一个最大堆
// 该构造堆的过程, 时间复杂度为O(n)
MaxHeap(Item arr[],int n)
{
data =new Item[n+1];
capacity = 0;
for(int i = 0;i < n;i++)
{
data[i+1] = arr[i];
count = n;
}
for(int i = count/2;i >= 1;i**)
{
shiftDnow(i);
}
}
int size()
{
return count;
}
bool isEmpty()
{
return count == 0;
}
void insert(Item item)
{
assert( count +1 <= capacity);
data[count + 1] = item;
count++;
shiftUp(count);
}
Item extracMax()
{
assert(count > 0);
Item ret = data[1];
swap(data[1],data(count));
count -- ;
shiftDnow(1);
return ret;
}
// 获取最大堆中的堆顶元素
Item getMax()
{
assert( count > 0 );
return data[1];
}
};