数据结构:堆及堆的应用


>  1. 堆:把一组数据按照完全二叉树的顺序储存模式存储在一个二维数组中,
>    若ai<ai+1&&ai<ai+2,则称为小堆,
>    若ai>ai+1&&ai>ai+2,则称为大堆(i=0,1,2...n);

这里写图片描述

  • 堆的特点:
  • 大堆:任意一个节点的值都比它的左右孩子节点的值大,且逐级递减;
  • 小堆:任意一个节点的值都比它的左右孩子节点的值小,且逐级递增;

在堆中,若设父亲节点为parent,则它的左孩子为2*parent+1,右孩子为2*parent+2;

  • > 堆的创建:
 void MakeHeap(DataType* a, size_t n)//构建堆
{
    int i=(n-1)>>1;
    for(;i>=0;i--)
    {
        AdjustDown(a,n,i);//向下调整函数
    }
}
- 向下调整函数:
void AdjustDown(DataType* a, size_t n, int root)//向下调整
{
    int parent =root;
    int child=2*parent+1;
    while(child<n)
    {
        if((child+1)<n&&a[child+1]<a[child])//右孩子存在且右孩子大于左孩子
        {
            ++child;//指向右孩子
        }
        if(a[child]<a[parent])
        {
            DataType tmp;
            tmp=a[child];
            a[child]=a[parent];
            a[parent]=tmp;

            parent=child;
            child=2*parent+1;
        }
        else
        {
            break;
        }

    }


}
  • 向上调整函数
    -
 void AdjustUp(DataType* a, size_t n, int child)//向上调整 
{
    int parent=(child-1)>>1;
    while(child>0)
    {
        if(a[child]<a[parent])
        {
            DataType tmp;
            tmp=a[child];
            a[child]=a[parent];
            a[parent]=tmp;

            child=parent;
            parent=(child-1)>>1;
        }
        else
        {
            break;
        }
    }

}

堆的应用:
1、海量数据top K问题:

  • 代码实现:
void TopK(DataType* a, size_t n, size_t k)
{
    int i;
    MakeHeap(a,k);//建小堆
    for(i=k;i<n;i++)
    {
        a[0]=a[i];
        AdjustDown(a,k,0);

    }
    for(i=0;i<k;i++)
    {
        printf("%d ",a[i]);
    }




}

2、优先级队列问题

  • 1.1 优先级队列的定义 •优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。
  • 1.2 优先级队列的特点
  • •优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值。 •当给每个元素分配一个数字来标记其优先级时,可设较小的数字具有较高的优先级,这样更方便地在一个集合中访问优先级最高的元素,并对其进行查找和删除操作。
    •在最小优先级队列(min PriorityQueue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素。
    •在最大优先级队列(maxPriorityQueue)中,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。 •插入操作均只是简单地把一个新的元素加入到队列中。
    •注:每个元素的优先级根据问题的要求而定。当从优先级队列中删除一个元素时,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。

初始化

void PriorityQueueInit(PriorityQueue* q)
{
    assert(q);
    q->_size=0;
    memset(q->_a,0,sizeof(DataType)*N);
}
  • 插入
void PriorityQueuePush(PriorityQueue* q, DataType x) 
{
    assert(q);
    if(q->_size>=N)
    {
    printf("PriorityQueuefull\n");
    return;
    }

    q->_a[q->_size++]=x;
     AdjustUp(q->_a,q->_size,q->_size-1);//从最后一个元素开始调


}
  • 删除
void PriorityQueuePop(PriorityQueue* q)
{
    assert(q);
    if(NULL==q)
    {
        printf("PriorityQueueEmpty\n");
        return;
    }
    q->_a[0]=q->_a[q->_size-1];
    q->_size--;
    AdjustDown(q->_a,q->_size,0);

}
  • 取队首元素
 - DataType PriorityQueueTop(PriorityQueue* q)
{
    assert(q);
    if(NULL==q)
    {
        printf("PriorityQueueEmpty\n");
        return;
    }

   return q->_a[0];
}
  • 判空

size_t PriorityQueueEmpty(PriorityQueue* q)
{
    assert(q);
    return q->_size;
}

3、堆排序

void HeapSort(DataType* a, size_t n)
{
    int i=0;
    assert(a);
    MakeHeap(a,n);

    while(n>0)
    {
    printf("%d ",a[0]);
    a[0]=a[n-1];
    n--;
    AdjustDown(a,n,0);
    }


}

源码:
Heap.h

#ifndef __HEAP_H_
#define __HEAP_H_

#include <stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType; 

void AdjustDown(DataType* a, size_t n, int root) ;//向下调整
void MakeHeap(DataType* a, size_t n) ;//构建堆
void AdjustUp(DataType* a, size_t n, int child);//向上调整 

// topk 最大的前K 
void TopK(DataType* a, size_t n, size_t k); 


#define N 1000 

typedef struct PriorityQueue 
{ 
    DataType _a[N]; 
    size_t _size; 

    //DataType* _a; 
    //size_t _size; 
    //size_t _capacity; 
}PriorityQueue; 

void PriorityQueueInit(PriorityQueue* q); 
void PriorityQueuePush(PriorityQueue* q, DataType x); 
void PriorityQueuePop(PriorityQueue* q); 
DataType PriorityQueueTop(PriorityQueue* q); 
size_t PriorityQueueSize(PriorityQueue* q); 
size_t PriorityQueueEmpty(PriorityQueue* q); 


void HeapSort(DataType* a, size_t n) ;
#endif

Heap.c

#include"Heap.h"
void MakeHeap(DataType* a, size_t n)//构建堆
{
    int i=(n-1)>>1;
    for(;i>=0;i--)
    {
        AdjustDown(a,n,i);
    }
}
void AdjustDown(DataType* a, size_t n, int root)//向下调整
{
    int parent =root;
    int child=2*parent+1;
    while(child<n)
    {
        if((child+1)<n&&a[child+1]<a[child])//右孩子存在且右孩子大于左孩子
        {
            ++child;//指向右孩子
        }
        if(a[child]<a[parent])
        {
            DataType tmp;
            tmp=a[child];
            a[child]=a[parent];
            a[parent]=tmp;

            parent=child;
            child=2*parent+1;
        }
        else
        {
            break;
        }

    }


}
void AdjustUp(DataType* a, size_t n, int child)//向上调整 
{
    int parent=(child-1)>>1;
    while(child>0)
    {
        if(a[child]<a[parent])
        {
            DataType tmp;
            tmp=a[child];
            a[child]=a[parent];
            a[parent]=tmp;

            child=parent;
            parent=(child-1)>>1;
        }
        else
        {
            break;
        }
    }

}
void TopK(DataType* a, size_t n, size_t k)
{
    int i;
    MakeHeap(a,k);//建小堆
    for(i=k;i<n;i++)
    {
        a[0]=a[i];
        AdjustDown(a,k,0);

    }
    for(i=0;i<k;i++)
    {
        printf("%d ",a[i]);
    }




}
void PriorityQueueInit(PriorityQueue* q)
{
    assert(q);
    q->_size=0;
    memset(q->_a,0,sizeof(DataType)*N);
}

void PriorityQueuePush(PriorityQueue* q, DataType x) 
{
    assert(q);
    if(q->_size>=N)
    {
    printf("PriorityQueuefull\n");
    return;
    }

    q->_a[q->_size++]=x;
     AdjustUp(q->_a,q->_size,q->_size-1);


}
void PriorityQueuePop(PriorityQueue* q)
{
    assert(q);
    if(NULL==q)
    {
        printf("PriorityQueueEmpty\n");
        return;
    }
    q->_a[0]=q->_a[q->_size-1];
    q->_size--;
    AdjustDown(q->_a,q->_size,0);





}
DataType PriorityQueueTop(PriorityQueue* q)
{
    assert(q);
    if(NULL==q)
    {
        printf("PriorityQueueEmpty\n");
        return;
    }

   return q->_a[0];
}
size_t PriorityQueueSize(PriorityQueue* q)
{
   assert(q);
   return q->_size;

}
size_t PriorityQueueEmpty(PriorityQueue* q)
{
    assert(q);
    return q->_size;
}
void HeapSort(DataType* a, size_t n)
{
    int i=0;
    assert(a);
    MakeHeap(a,n);



    while(n>0)
    {
    printf("%d ",a[0]);
    a[0]=a[n-1];
    n--;
    AdjustDown(a,n,0);
    }


}

test.c

#include"Heap.h"
void TestHeap() 
{ 
    int i=0;
    DataType NArray[1000]; 
    DataType a[] = {10,11, 13, 12, 16, 18, 15, 17, 14, 19};
    HeaapSort(a,sizeof(a)/sizeof(a[0]));
    printf("\n");
    MakeHeap(a, sizeof(a)/sizeof(DataType)); 


    srand(time(0)); 
    for (i = 0; i < 1000; ++i) 
    { 
    NArray[i] = rand()%10000; 
    } 

    NArray[30] = 10001; 
    NArray[350] = 10002; 
    NArray[999] = 10003; 
    NArray[158] = 10004; 
    NArray[334] = 10005; 

    TopK(NArray, 1000, 5); 
} 
void TestPriorityQueue() 
{ 
    PriorityQueue q; 
    PriorityQueueInit(&q); 
    PriorityQueuePush(&q, 5); 
    PriorityQueuePush(&q, 2); 
    PriorityQueuePush(&q, 3); 
    PriorityQueuePush(&q, 7); 
    PriorityQueuePush(&q, 6); 
    PriorityQueuePush(&q, 1); 
    PriorityQueuePush(&q, 4); 


    while (PriorityQueueEmpty(&q) != 0) 
    { 
    printf("%d ", PriorityQueueTop(&q)); 
    PriorityQueuePop(&q); 
    } 
    printf("\n"); 
} 
int main()
{
    TestHeap();
    printf("\n");
    TestPriorityQueue();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值