调研报告:堆排序与优先队列(C语言)

本文探讨了在C语言中实现堆排序和优先队列的方法。通过介绍最小堆和最大堆的概念,阐述了堆作为数据结构在处理大量数据时的优势。堆排序算法通过构建和调整堆来实现排序,而优先队列则在查找最大元素时提供了高效性能。文中还给出了C语言的代码示例,展示如何构建和操作这两个数据结构。
摘要由CSDN通过智能技术生成

:电子科技大学 格拉斯哥学院 2017级 徐方则
虽然这是老师强制要求的作业,要写与新生研讨课(雷达通信,图像识别。。。)有关的科普调研博客。但对比大多数科普论文(参见其它抬头带相同格式的博客),它们其实讲得已经很清楚了。而且它们也含有相当大的缺点:其实很多是有原版的,即不是原创。
在如今这个python满天飞的信息时代里,许多人可能会问自己:学C语言有用吗?本次报告便想从底层一些很简单的例子来说明C语言在这些领域的应用。说到C,就一定离不开数据结构。在大量数据需处理时,不同算法与相应的数据结构的选择所花的时间与空间可能是天差地别。这里我想讲一讲堆排序和优先队列。
下面从百度百科里找了张堆的图片,这是一个建最小堆(e)的过程。我们可以发现最小堆一个很显而易见的特性,子节点的值永远比父节点大。而最大堆与其相反,子节点的值永远比父节点小。

在这里插入图片描述
结合树的性质,堆其实是一个完全二叉树。根据这一点,若我们把堆存储在数组里,把第一个的下标当成1,我们不难发现,左儿子对应的下标是父节点下表的两倍,右儿子是父节点的两倍加一,以此,我们便可以编码建堆了。其算法复杂度较为紧确的界为O(n)。
在这里插入图片描述
第一张图其实已经讲了如何建最小堆,从根结点开始,若其比子节点大,选取子节点中最小的与其互换,一直执行到叶节点。
而堆排序更为简单,只要将堆顶的值取出,并将剩余的数组重新建堆即可。
以下是c语言代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct node MaxHeap;
struct node{
    int *a;
    int size;
};
void ArrayToMaxHeap(MaxHeap *heap,int *n);
void MaxHeapify(MaxHeap *heap,int i);
void BuildMaxHeap(MaxHeap *heap);
void MaxHeapSort(MaxHeap *heap);
int main(int argc, const char * argv[]) {
    time_t start,finish;
    float time=0;
    int i,n;
    MaxHeap heap;
    ArrayToMaxHeap(&heap,&n);
    BuildMaxHeap(&heap);
        start=clock();
    MaxHeapSort(&heap);
     finish=clock();
    for(i=1;i<n;i++)printf("%6d",heap.a[i]);
    time=(float)(finish-start)/CLOCKS_PER_SEC;
    printf("\n%5f\nHello, World!\n",time);
    return 0;
}

void ArrayToMaxHeap(MaxHeap *heap,int *n){
    int num,i;
    scanf("%d",&num);
    num+=1;//set heap[0] to be the biggest one, which is not included in the following sorting
    heap->a=malloc(num*sizeof(int));
    for(i=0;i<num;i++)scanf("%d",&heap->a[i]);
    heap->size=num-1;
    *n=num;
}

void MaxHeapify(MaxHeap *heap,int i){
    int l,r,largest,tmp;
    tmp=0;
    largest=0;
    l=i*2;
    r=i*2+1;
    if(l<=heap->size&&heap->a[l]>heap->a[i])
        largest=l;
    else largest=i;
    if(r<=heap->size&&heap->a[r]>heap->a[largest])
        largest=r;
    if(largest!=i){
        tmp=heap->a[i];
        heap->a[i]=heap->a[largest];
        heap->a[largest]=tmp;
        MaxHeapify(heap,largest);
    }
}

void BuildMaxHeap(MaxHeap *heap){
    int i;
    i=heap->size/2;
    for(;i>=1;i--)
        MaxHeapify(heap,i);
}

void MaxHeapSort(MaxHeap *heap){
    int i,tmp;
    for(i=heap->size;i>1;i--){
        tmp=heap->a[i];
        heap->a[i]=heap->a[1];
        heap->a[1]=tmp;
        heap->size--;
        MaxHeapify(heap,1);
}
}

而优先队列与堆排序很像,相当于将最大的数逐一从队列中取出,但其本身复杂度(优先队列)要比排序低不少,当然更比直接暴力求最大快多了。
以下是c优先队列代码,基本沿用了上面的代码

#include <stdio.h>
#include <stdlib.h>

//***************************HEAP PART************************************
typedef struct node MaxHeap;
struct node{
    int *a;
    int size;
};
void ArrayToMaxHeap(MaxHeap *heap,int *n);
void MaxHeapify(MaxHeap *heap,int i);
void BuildMaxHeap(MaxHeap *heap);
void MaxHeapSort(MaxHeap *heap);
//************************************PRIORITY QUEUE PART*************************
int HeapExtractMax(MaxHeap *heap);
int Maximum(MaxHeap *heap);
void HeapIncreaseKey(MaxHeap *heap,int i,int k);
void MaxHeapInsert(MaxHeap *heap,int key);
//********************************MAIN FUNCTION***************************
int main(int argc, const char * argv[]) {
    int n;
    int key;
    MaxHeap heap;
    printf("Array numbers:\n");
    ArrayToMaxHeap(&heap,&n);
    BuildMaxHeap(&heap);
    printf("Insert number:\n");
    scanf("%d",&key);
    MaxHeapInsert(&heap,key);
    printf("The maximum number is:%d\n",Maximum(&heap));
    return 0;
}
//********************************HEAP PART***************************
void ArrayToMaxHeap(MaxHeap *heap,int *n){
    int num,i;
    scanf("%d",&num);
    num++;//set heap[0] to be the biggest one, which is not included in the following sorting
    heap->a=(int *)malloc(num*sizeof(int));
    for(i=0;i<num;i++)scanf("%d",&heap->a[i]);
    heap->size=num-1;
    *n=num;
}
void MaxHeapify(MaxHeap *heap,int i){
    int l,r,largest,tmp;
    tmp=0;
    largest=0;
    l=i*2;
    r=i*2+1;
    if(l<=heap->size&&heap->a[l]>heap->a[i])
        largest=l;
    else largest=i;
    if(r<=heap->size&&heap->a[r]>heap->a[largest])
        largest=r;
    if(largest!=i){
        tmp=heap->a[i];
        heap->a[i]=heap->a[largest];
        heap->a[largest]=tmp;
        MaxHeapify(heap,largest);
    }
}
void BuildMaxHeap(MaxHeap *heap){
    int i;
    i=heap->size/2;
    for(;i>=1;i--)
        MaxHeapify(heap,i);
}
void MaxHeapSort(MaxHeap *heap){
    int i,tmp;
    for(i=heap->size;i>1;i--){
        tmp=heap->a[i];
        heap->a[i]=heap->a[1];
        heap->a[1]=tmp;
        heap->size--;
        MaxHeapify(heap,1);
    }
}
//******************************PRIORITY PART********************
int HeapExtractMax(MaxHeap *heap){
    int max=0;
    if(heap->size<1)
    {
        printf("Heap underflow!");
        return 0;
    }
    max=heap->a[1];
    heap->a[1]=heap->a[heap->size];
    MaxHeapify(heap,1);
    heap->size--;
    return max;
}
int Maximum(MaxHeap *heap){
    return heap->a[1];
}
void HeapIncreaseKey(MaxHeap *heap,int i,int k){
    if(k<heap->a[i]){
        printf("Key is smaller than the original value");
        return ;
    }
    heap->a[i]=k;
    while(i>1&&heap->a[i/2]<heap->a[i]){
        heap->a[i]=heap->a[i/2];
          i/=2;
        heap->a[i]=k;
    }
}
void MaxHeapInsert(MaxHeap *heap,int key){
    heap->size++;
    heap->a=realloc(heap->a,(heap->size+1)*sizeof(int));
    heap->a[heap->size]=key;
    HeapIncreaseKey(heap,heap->size,heap->a[heap->size]);
}

最大堆最小堆本身应用相当的多,比如优化问题。可以通过一定模型将一个事件的优先度转化为数字,再从中提取优先度最高的,比如最大似然估计里,对不同的点估计有不同的值,将每个点的数值做成优先队列。那么maimum likelihood estimator(其实就是最大似然估计的值) 就可以看成是一个优先队列里最大的数,而采集的样本越多,值越准确,所以其需要大量的数据。在大量数据下,堆就不失为一个很好的数据结构,应为其本身的复杂度为O(n),比O(nlogn)快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值