堆排序、优先队列

1.堆排序

a.堆的定义

n个元素序列{k1,k2,...,kn}当且仅当满足以下关系时,称之为堆。

ki<=k2i且ki<=k2i+1 (小根堆)
ki>=k2i且ki>=k2i+1 (大根堆)

以下针对最大堆

b.维护堆的性质

Max-Heapify通过让A[i]的值在最大堆中"逐级下降"(A[i]的值小于其左右孩子的值时),从而使得以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
        swap(A[i],A[largest])
        Max-Heapify(A,largest)

时间复杂度:O(lgn)

c.建堆

子数组A(n/2+1..n)中的元素都是树的叶子结点,每个叶结点都可以看成只包含一个元素的堆.Build-Max-Heap对树中的其他结点都调用一次Max-Heapify.

Build-Max-Heap(A)
    A.heap-size = A.length
    for i = A.length/2 downto 1
        Max-Heapify(A,i)

时间复杂度:O(n)

d.堆排序

Heap-Sort(A)
    Build-Max-Heap(A)
    for i = A.length downto 2
        swap(A[1],A[i])
        A.heap-size = A.heap-size -1
        Max-Heapify(A,1)

时间复杂度:O(n*lgn)

2.优先队列

具体的算法就不谈了,来看下C++中的优先队列如何使用.

std::priority_queue
Defined in header <queue>
template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

默认是最大优先队列.可以提供Compare参数来实现最大优先队列.

Compare = greater<T>

Example:

#include <functional>
#include <queue>
#include <vector>
#include <iostream>

template<typename T> void print_queue(T& q) {
    while(!q.empty()) {
        std::cout << q.top() << " ";
        q.pop();
    }
    std::cout << ‘\n‘;
}

int main() {
    std::priority_queue<int> q;

    for(int n : {1,8,5,6,3,4,0,9,3,2})
        q.push(n);

    print_queue(q);

    std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

    for(int n : {1,8,5,6,3,4,0,9,3,2})
        q2.push(n);

    print_queue(q2);
}

对于自定义类型

如果重载了比较运算符

priority_queue<T> Q//最大优先队列
priority_queue<T,vector<T>,greater<T>> Q//最小优先队列

如果没有重载比较运算符,则需要提供一个Comparator传给Compare参数

//最大优先队列比较器
struct comp
{
    bool operator () (T &a,T &b) const {
        return a.key < b.key;
    }
};
//最小优先队列比较器
struct comp
{
    bool operator () (T &a,T &b) const {
        return a.key > b.key;
    }
};
//使用
priority_queue<T,vector<T>,comp> Q

参考:1,2,3

时间: 2024-10-07 03:06:40

堆排序、优先队列的相关文章

利用堆实现堆排序&amp;优先队列

数据结构之(二叉)堆 一文末尾提到"利用堆可以实现:堆排序.优先队列".本文代码实现之. 1.堆排序 假设要将无序数组按非递减(递增)排序,则应使用大(小)顶堆.这里涉及到大堆排序涉及到三种操作:(1).MaxHeapify操作(自顶向下即SiftDown操作):(2).BuildMaxHeap操作(线性时间内将无序数组构造成一个最大堆):(3)将堆顶元素和堆的最后一个元素交换,并将堆元素大小减去1,对堆顶元素调用MaxHeapify操作重新调整为大顶堆,重复直到数组有序.下面是详细的

堆与堆排序—优先队列

上一节我们写了树以及二叉树的知识 http://blog.csdn.net/wtyvhreal/article/details/43487095 堆是一种特殊的完全二叉树. 所有父节点都比子节点要小,这样的完全二叉树称为最小堆,反之叫最大堆. 下图一棵完全二叉树,调整为最小堆步骤: 向下调整的代码如下: 从上面可以得到:调整堆的时间复杂度是O(logN). 如果堆的大小为N,那么插入一个新元素所需要的时间为O(logN). 在刚刚那个最小堆里插入数值3 向上调整的代码如下: 建堆:从空的堆开始,

优先队列和堆排序

优先队列 堆 1 基于堆的算法 初始化 自底向上堆化 自顶向下堆化 插入删除一项 2 堆排序 优先队列全部代码 1 优先队列 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有最高级先出 (largest-in,first-out)的行为特征. 优先队列支持两种基本操作:向优先队列中插入一个新的数据项,删除(最大)优先队列中关键字最大的数据项. 优先队列具有很好的灵活性,能支持的操作: -

数据结构--优先队列(堆排序)

数据结构--优先队列(堆排序) 优先队列:不是先进先出啦,下面的代码是大顶堆,大的先出. 在之前理解堆排序的基础上,在来理解优先队列. 还是用这个公式: leftNo = parentNo*2+1 rightNo = parentNo*2+2 parentNo = (nodeNo-1)/2 每次进队列是从最后进,在慢慢上浮. 每次出队列,堆顶先出,在把队尾调到堆顶,在下浮. 上代码 package sy181002; import java.util.Arrays; /** * 优先队列 * *

快排、归并排序(分治)、堆排序

一.快速排序 1)算法简介 快速排序是由C. A. R. Hoare所发展的一种排序算法.其基本思想是基本思想是,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. 2)算法描述 快速排序使用分治法来把一个串(list)分为两个子串行(sub-lists). 步骤为: 1.从数列中挑出一个元素,称为 "基准"(pivot), 2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准

算法导论学习之堆+堆排序+堆构成优先队列

注:堆分为最大堆和最小堆两种,下面我们讨论的堆都是指的最大堆,最小堆的性质与其是类似的. 堆数据结构是一种数组对象,可以被视为一棵完全二叉树(这棵二叉树除最后一层外,其余每层都是填满的):我们用一个数组来存储一个堆,表示堆的数组有两个属性:length[A]表示的是数组中的元素个数,headsize[A]表示堆中元素个数(也就是说数组中的元素不一定都是堆中的元素). 下面不加证明的给出一些堆的性质: 对于任何一个节点,其父节点为i/2(i>1):左儿子:2*i,右儿子:2*i+1; 对于最大堆每

堆排序与优先队列&mdash;&mdash;算法导论(7)

1. 预备知识 (1) 基本概念     如图,(二叉)堆一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组A包括两个属性:A.length给出了数组的长度:A.heap-size表示有多少个堆元素保存在该数组中(因为A中可能只有部分位置存放的是堆的有效元素).     由于堆的这种特殊的结构,我们可以很容易根据一个结点的下标i计算出它的父节点.左孩子.右孩子的下标.计算公式如下: parent(i) =

第六章 堆排序 6.5 优先队列

package chap06_Heap_Sort; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import org.junit.Test; /** * 优先队列,二叉堆数组实现,数组的size最好大一些,至少比里面的堆大一些,来实现堆的扩展(插入元素) * * @author xiaojintao * */ public class PriorityQueue {

算法2.4——优先队列与堆排序

优先队列(Priority Queues)的使用和队列(删除最老的元素)以及栈(删除最新的元素)类似.举个实用例子:也就是从10亿个元素中选出最大的10个,有了优先队列,就只需要用一个能存储10个元素的队列即可. 而二叉堆很好实现优先队列的基本操作.其中二叉堆是一组能够用队友徐的完全二叉树排序的元素.其中关于堆的算法,有上浮swim和下沉sink,另外一般来说A[0]不使用,直接使用A[1]. 堆排序的实现 实现堆排序需要解决两个问题: 1.如何由一个无序序列建成一个堆? 2.如何在输出堆顶元素

堆数据结构+堆排序+最大优先队列的堆的实现

对于堆排序,首先要先知道什么是堆数据结构,堆数据结构就是一个完全二叉树,但是它有自己的性质. 例如最大堆的性质为:A[PARENT[i]]>=A[i]:即每一个结点的值大于等于其左右孩子的值,小于等于其父节点的值.我们在这里只讨论最大堆的情况.我们知道一颗完全二叉树对应一个最大堆的形式,我们要做的就是将二叉树转化为最大堆,这就是所谓的最大堆的维护,我们定义函数MaxheapFY(A,i)来进行操作. 代码: /** *MaxheapFY(A,i):维护位置i最大堆性质,此时假设left(i)和r