数据结构之堆(优先队列)

堆和优先队列

堆—尾部插入调整,从最后一层插入,自下向上调整,

堆–头部弹出调整,删除堆顶的元素,将堆尾的元素放到堆顶,维护完全二叉树,然后调整顺序

堆----优先队列

堆排序

  • 将堆顶元素与堆尾元素交换
  • 将此操作看作是堆顶元素的弹出操作
  • 按照头部弹出以后的策略调整堆
#include<stdio.h>
#include<time.h>
#include<stdlib.h>


#define swap(a,b){\
    __typeof(a) __temp=a;\
    a=b;b=__temp;\
}

typedef struct pri_queue{
    int *data;
    int cnt ,size;
}pri_queue;

//优先队列的初始化
pri_queue *init(int n){
    pri_queue *q = (pri_queue *)malloc(sizeof(pri_queue));
    q->data=(int *)malloc(sizeof(int)*(n+1));
    q->cnt=0;
    q->size=n;
    return q;
}
//释放内存
void clear(pri_queue *q){
    if(q==NULL)return ;
    free(q->data);
    free(q);
    return ;
}
//判断是否为空
int empty(pri_queue *q){
    return q->cnt==0;
}

int top(pri_queue *q){
    return q->data[1];
}
//插入操作,自下向上判断,
int push(pri_queue *q,int val){
    if(q==NULL) return 0;
    if(q->cnt==q->size) return 0;
    q->data[++(q->cnt)]=val;
    //插入调整,
    int ind=q->cnt;
    //父节点不为零且当前值比父节点指大,交换
    while(ind >>1&&q->data[ind]>q->data[ind>>1]){
        swap(q->data[ind],q->data[ind>>1]);
        ind>>=1;
    }
    return 1;
}
//弹出操作,自上向下判断,调整堆
int pop(pri_queue *q){
    if(q==NULL) return 0;
    if(empty(q)) return 0;
    q->data[1]=q->data[q->cnt--];
    int ind=1;
    //左孩子变量合法
    while((ind<<1)<=q->cnt){
        int temp=ind,l=ind<<1,r=ind<<1|1;
        if(q->data[l]>q->data[temp]) temp =l;
        //右孩子结点要小于容量的值
        if(r<=q->cnt&&q->data[r]>q->data[temp]) temp=r;
        if(temp==ind) break;
        swap(q->data[temp],q->data[ind]);
        ind =temp;
    }
    return 1;
}


int main(){
    srand(time(0));
    #define max_op 20
    pri_queue *q=init(max_op);
//循环创建max-op个元素,并且插入到优先队列
    for(int i=0;i<max_op;i++){
        int val=rand()%100;
        push(q,val);
        printf("insert %d to the pri_queue \n",val);
    }
    for(int i=0;i<max_op;i++){
        printf("%d ",top(q));
        pop(q);
    }
    printf("\n");
    clear(q);
    #undef max_op 
    return 0;
}

应用–堆排序

#include<iostream>
using namespace std;

void HeapAdjust(int *arr,int n,int i){
    int smallest=i;
    int l=2*i+1;
    int r=2*i+2;
    if(l<n&&arr[l]<arr[smallest])
        smallest=l;
    if(r<n&&arr[r]<arr[smallest])
        smallest=r;
    if(smallest!=i){  
        swap(arr[smallest],arr[i]);
        i=smallest;
        //递归调用
        HeapAdjust(arr,n,i);
    }
}

void HeapSort(int *arr,int n){
    for(int i=n/2;i>=0;i--){
        HeapAdjust(arr,n,i);
    }
    for(int i=n;i>=0;i--){
        swap(arr[0],arr[i]);
        HeapAdjust(arr,i-1,0);
    }
}

int main(){
    int arr[10]={12,4,5,2,1,12,8,9,11,10};
    int len=sizeof(arr)/sizeof(int);
    HeapSort(arr,len-1);
    for(int i=0;i<len;i++){
        cout<<arr[i]<<" ";
    }
    cout<<endl;
    return 0;
}



//根据数据结构优先队列改进而来
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>

using namespace std;

void heapadjust(int *arr,int n,int ind){
    while((ind<<1|1)<=n){
        int temp=ind,l=ind<<1|1,r=2*ind+2;
        if(arr[temp]<arr[l]) temp=l;
        if(r<=n&&arr[temp]<arr[r]) temp=r;
        if(temp==ind) break;
        swap(arr[temp],arr[ind]);
        ind = temp;
    }
    return;
}

void heapsort(int *arr,int n){
    for(int i=n>>1;i>=0;i--){
        heapadjust(arr,n,i);
    }
    for(int i=n;i>=0;i--){
        swap(arr[i],arr[0]);
        heapadjust(arr,i-1,0);
    }
}

void output(int *arr,int n){
    cout<<'[';
    for(int i=0;i<n;i++){
        cout<<arr[i]<<" ";
    }
    cout<<']'<<endl;
}

int main(){
    srand(time(0));
    #define max_n 20
    int *arr=new int [max_n];
    for(int i=0;i<max_n;i++){
        arr[i]=rand()%100;
    }
    output(arr,max_n);
    heapsort(arr,max_n);
    output(arr,max_n);
    delete[]arr;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值