zoukankan      html  css  js  c++  java
  • 优先队列与堆

    1、定义:将优先级最高的元素先出队列的队列。

    2、基本操作:入队(插入),出队(删除优先级最高的元素,代码中以元素值最小为优先级最高),构建堆,

    修改元素等。

    3、二叉堆:父节点小于子节点的完全二叉树。

    性质:

    (1)结构性:完全二叉树结构

    (2)堆序性:父节点的值小于子节点的值

    3、代码实现:

    (1)堆的结构:用线性表顺序存储实现即可,不需要复杂的指针。

    struct Node{
        int *data;
        int Capcity,size;
    };
    typedef struct Node* PriorityQueue;

    (2)堆的插入(优先队列的入队):

    先在数组后分配一个新的空间,然后寻找x要插入的位置,将x与大于它的父节点进行交换(上滤),

    直到再次满足堆的堆序性。

    void Insert(int x,PriorityQueue Q) //插入 
    {
        if(IsFull(Q)){
            printf("The Queue is Full
    ");
            return ;
        }
        int i;
        for(i=++Q->size;Q->data[i/2]>x;i/=2) //上滤 
        Q->data[i]=Q->data[i/2];
        Q->data[i]=x;
    }

    (2)堆的删除最小值(优先队列的出队):

    直接将头结点出队,然后不断向下调整,选取子节点中较小的值变为根节点,然后再调整改变较小的子节点(下滤),使堆重新有序。

    int DeleteMin(PriorityQueue Q) //出队 
    {
        if(IsEmpty(Q)){
            printf("The Queue is Empty!!!
    ");
            return -1;
        }
        int i,MI=Q->data[1],child,Last=Q->data[Q->size--];
        for(i=1;i*2<=Q->size;i=child) //下滤 
        {
            child=i*2;
            if(Q->size!=child&&Q->data[child+1]<Q->data[child]) child++;
            if(Last>Q->data[child]) Q->data[i]=Q->data[child];
            else break;
        }
        Q->data[i]=Last;
        return MI;
    }

    (3)堆的上滤和下滤:

    上滤:从要调整的值开始,不断将当前值向上移动,直到位置合适(画图更好理解)。

    void PrecolateUp(int pos,PriorityQueue Q) //上滤 
    {
        int i,x=Q->data[pos];
        for(i=pos;Q->data[i/2]>x;i/=2)
        Q->data[i]=Q->data[i/2];
        Q->data[i]=x;
    }

    下滤:与上滤相反

    void PrecolateDown(int pos,PriorityQueue Q) //下滤 
    {
        int i,Last=Q->data[pos],child;
        for(i=pos;i*2<=Q->size;i=child)
        {
            child=i*2;
            if(child!=Q->size&&Q->data[child+1]<Q->data[child]) child++; //考虑是否有单个节点 
            if(Last>Q->data[child]) Q->data[i]=Q->data[child];
            else break;
        }
        Q->data[i]=Last;
    }

    (4)堆的修改:

    增值:先增加当前值,然后下滤

    void IncreaseKey(int pos,int x,PriorityQueue Q)
    {
        if(IsEmpty(Q)) return ;
        Q->data[pos]+=x;
        PrecolateDown(pos,Q);
    }

    降值:先减小当前值,然后上滤

    void IncreaseKey(int pos,int x,PriorityQueue Q)
    {
        if(IsEmpty(Q)) return ;
        Q->data[pos]+=x;
        PrecolateDown(pos,Q);
    }

    (5)堆的删除:

    先将这个值减小为负无穷,再删除最小值。

    void Delete(int pos,PriorityQueue Q) //删除某一位置的元素 
    {
        if(IsEmpty(Q)) return ;
        int tmp=INT_MAX,i;
        DecreaseKey(pos,tmp,Q);
        DeleteMin(Q);
    }

    (6)构建堆:

    从叶子节点的父节点开始调整,使第i层及以下序列有序,然后向上调整(用于堆排序)。

    void BuildHeap(PriorityQueue Q) //构建堆 
    {
        for(int i=Q->size/2;i>0;i--)
        PrecolateDown(i,Q);
    }

    总代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 1200;
    const int MINSIZE = 3;
    struct Node{
        int *data;
        int Capcity,size;
    };
    typedef struct Node* PriorityQueue;
    PriorityQueue Init(int size) //初始化 
    {
        PriorityQueue Q=new Node;
        if(Q==NULL) printf("Ouf of Space!!!
    ");
        if(size<MINSIZE) printf("Too Small
    ");
        Q->data=new int[size+1];
        if(Q->data==NULL){
            printf("Ouf of Space!!!
    ");
        }
        Q->Capcity=size;
        Q->size=0;
        Q->data[0]=INT_MIN;
        return Q;
    } 
    bool IsEmpty(PriorityQueue Q) 
    {
        return Q->size==0;
    }
    bool IsFull(PriorityQueue Q)
    {
        return Q->size>Q->Capcity;
    }
    
    void PrecolateUp(int pos,PriorityQueue Q) //上滤 
    {
        int i,x=Q->data[pos];
        for(i=pos;Q->data[i/2]>x;i/=2)
        Q->data[i]=Q->data[i/2];
        Q->data[i]=x;
    }
    void PrecolateDown(int pos,PriorityQueue Q) //下滤 
    {
        int i,Last=Q->data[pos],child;
        for(i=pos;i*2<=Q->size;i=child)
        {
            child=i*2;
            if(child!=Q->size&&Q->data[child+1]<Q->data[child]) child++; //考虑是否有单个节点 
            if(Last>Q->data[child]) Q->data[i]=Q->data[child];
            else break;
        }
        Q->data[i]=Last;
    }
    
    void Insert(int x,PriorityQueue Q) //插入 
    {
        if(IsFull(Q)){
            printf("The Queue is Full
    ");
            return ;
        }
        int i;
        for(i=++Q->size;Q->data[i/2]>x;i/=2) //上滤 
        Q->data[i]=Q->data[i/2];
        Q->data[i]=x;
    }
    
    //修改 
    void DecreaseKey(int pos,int x,PriorityQueue Q)
    {
        if(IsEmpty(Q)) return ;
        Q->data[pos]-=x;
        PrecolateUp(pos,Q); 
    }
    void IncreaseKey(int pos,int x,PriorityQueue Q)
    {
        if(IsEmpty(Q)) return ;
        Q->data[pos]+=x;
        PrecolateDown(pos,Q);
    }
    
    void BuildHeap(PriorityQueue Q) //构建堆 
    {
        for(int i=Q->size/2;i>0;i--)
        PrecolateDown(i,Q);
    }
    int DeleteMin(PriorityQueue Q) //出队 
    {
        if(IsEmpty(Q)){
            printf("The Queue is Empty!!!
    ");
            return -1;
        }
        int i,MI=Q->data[1],child,Last=Q->data[Q->size--];
        for(i=1;i*2<=Q->size;i=child) //下滤 
        {
            child=i*2;
            if(Q->size!=child&&Q->data[child+1]<Q->data[child]) child++;
            if(Last>Q->data[child]) Q->data[i]=Q->data[child];
            else break;
        }
        Q->data[i]=Last;
        return MI;
    }
    void Delete(int pos,PriorityQueue Q) //删除某一位置的元素 
    {
        if(IsEmpty(Q)) return ;
        int tmp=INT_MAX,i;
        DecreaseKey(pos,tmp,Q);
        DeleteMin(Q);
    }
    void Print(PriorityQueue Q)
    {
        while(!IsEmpty(Q)){
            int x=DeleteMin(Q);
            printf("%d ",x);
        }
        printf("
    ");
    } 
    int main(void)
    {
        int n,i,x;
        scanf("%d",&n);
        PriorityQueue Q=Init(n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&x);
            Insert(x,Q);
        }
        IncreaseKey(3,99,Q);
        DecreaseKey(5,1000,Q);
        Delete(1,Q);
        Print(Q);
        
        return 0;
    }
    /*
    测试数据:
    5
    12 34 11 5 6
    */ 
    View Code
  • 相关阅读:
    linux常用命令笔记
    head first html与css
    多线程编程核心技术日记
    nio
    排序算法
    随笔
    数据库读写分离
    购物网站设计
    http
    servlet初始化
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10327502.html
Copyright © 2011-2022 走看看