优先队列
普通队列:先进先出,后进后出
优先队列:出队顺序和入队顺序无关,只与优先级有关;可以方便地动态选择优先级最高的任务执行
优先队列的实现:
(1)普通数组:入队O(1),出队O(n)
(2)顺序数组:入队O(n),出队O(1)
(3)堆:入队O(logn),出队O(logn)
堆
堆是一棵完全二叉树。最大堆中,节点的值总是不大于其父节点的值。
使用数组存储堆:
Shift Up 操作:新加入堆的元素,与其父节点进行比较,若新元素大,则与父节点交换位置,使堆满足最大堆的基本要求
Shift Down 操作:弹出堆中最大的元素(堆顶元素)后,将数组尾部元素填补到堆顶,而后将该元素和两个子节点元素较大的那个进行比较,若该元素小,则与子节点交换位置,直至该元素大于两个子节点或已进入堆的最后一层
Heapify 操作:对于前n/2个元素(即非叶子节点的元素)进行 Shift Down 操作,使之成为最大堆
比较:将n个元素逐个插入到空堆当中,算法复杂度为O(nlogn);使用Heapify操作,算法复杂度为O(n)
堆排序
算法描述:每次从堆中弹出队首,即为最大的元素,与队尾进行交换操作;则蓝色有序部分长度加1,重复操作
堆结构:
代码实现:
template<typename T>
void heapSort(T arr[], int n){
for( int i = (n-1)/2 ; i >= 0 ; i -- )
__shiftDown(arr, n, i);
for( int i = n-1; i > 0 ; i-- ){
swap( arr[0] , arr[i] );
__shiftDown(arr, i, 0);
}
}
最大索引堆
数据结构:使用index保存数据存放的位置,而数据存放在data当中;构建堆的过程中,修改的是index的内容;rev用于反向查找,表示索引在堆中的位置
最大索引堆可以很方便地修改,查找复杂类型的数据
关系如下:
最大最小队列
二项堆
斐波那契堆