In-place Heap Sorting就地堆排序

Experimental ReportLab

一、实验名称:In-place Heap Sorting

二、实验目的:

  1. 熟练掌握最大堆的数据结构,结构的特点;
  2. 能够实现最大堆的基本操作:如构造,插入,删除,初始化,回收内存等
  3. 利用最大堆实现堆排序
    三、实验内容:
  4. Determine the array structures for a complete max-heap(以数组形式表示的树结构)
  5. Input a linear list of 20 random numbers, building a complete max-heap to store the numbers by the process of in-place heapification
  6. Implement an in-place sorting, making use of POP operation for the built complete max-heaps .
    (End)
    四. 算法实现:
    堆排序算法可以分为两部分。
    在第一步中,构造堆。通常将堆放置在具有完整二叉树布局的数组中。完整的二叉树将二叉树结构映射到数组索引中;每个数组索引代表一个节点;节点的父级,左子级分支或右子级分支的索引是简单表达式。对于从零开始的数组,根节点存储在索引0处;如果i是当前节点的索引,则
    //堆从数组的1号节点开始存储
    若Parent = i,
    LeftChild = 2 * i,
    RightChild = 2 * i
    在第二步中,通过从堆(堆的根)中重复删除最大的元素,然后将其插入到数组中,来创建排序后的数组。每次删除后都会更新堆,以维护堆属性。一旦从堆中删除了所有对象,结果就是一个排序数组。
    堆排序可以在原地执行。数组可以分为两部分,排序后的数组和堆。此处以堆的形式存储了数组。每次弹出后都会保留堆的不变性,因此此过程唯一的成本就是弹出的成本。
    实现该步骤的代码:
    for(i=realSize;i>0;i–){
    h->data[i]=PopMaxHeap(h);
    printf("%d ", h->data[i]);
    }

Heapsort算法涉及通过首先将数组转换为最大堆。然后反复将列表的第一个值与最后一个值交换,并在堆操作中考虑到的值的范围减一,
。重复此过程,直到堆操作所考虑的值的范围长度为一。

这些步骤是:

  1. 在数组上调用buildMaxHeap()函数。它从O(n)操作中的数组构建一个堆。
  2. 将数组的第一个元素与最后一个元素交换。将堆操作的考虑范围减小一。(程序直接让未弹出的堆的最后一个元素等于弹出元素,弹出过程实现了将堆操作的考虑范围减小一)
  3. 调用数组中的FixDown()函数,将新的第一个元素筛选到堆中相应的索引。
  4. 除非数组的考虑范围是一个元素,否则请转到步骤(2)。
    buildMaxHeap()操作运行一次,性能为O(n)。FixDown()函数为O(log n),并被调用n次。因此,该算法的性能为O(n + n log n)= O(n log n)。

四. 程序清单(较为详细的注释):

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MaxSize 100
typedef struct Hnode* MaxHeap;
struct Hnode{
    int* data;
    int size;
    int Capacity;
};
int getRandomNum(){
    int RandomNum;
    RandomNum=rand();
    return  RandomNum;
}
/*Filter down and find the proper position of the node on the premise that all subtrees are the MaxHeap. 
The tree with this node as the root node is a smallest heap*/
void FixDown(MaxHeap h,int index){
    int parent;
    int child;
    int temp=h->data[index];
    for(parent=index;parent*2<=h->size;parent=child){
        child=parent*2;
        if(child+1<=h->size&&h->data[child+1]>h->data[child])
            child++;
        if(h->data[child]>temp){
            h->data[parent]=h->data[child];
        }
        else break;
    }
    h->data[parent]=temp;
}
/*The idea of recursion is adopted to establish the minimum heap from bottom to top, which ensures 
that the subtrees currently established are all the smallest heaps.*/
void BuildMaxHeap(MaxHeap h){
    int i;
    for(i=h->size/2;i>=1;i--){
        FixDown(h,i);
    }
}
//Determine whether the MinHeap is empty
int Empty(MaxHeap h){
    return h->size==0;
}
//Return and delete the max value of the max heap (that is, the head node), and keep the tree as the max heap
/*Move the last node to the head node, and size--,
Because the subtrees are all the MaxHeap at this time, filtering directly 
down can ensure that the tree is still the MaxHeap*/
int PopMaxHeap(MaxHeap h){
    if(Empty(h)){
        printf("The MaxHeap is empty, and the popped -11111 is an invalid value\n");
        return -11111;
    }
    int result=h->data[1];
    h->data[1]=h->data[(h->size)--];
    //向下过滤
    FixDown(h,1);
    return result;
}
/*Insert node, keep MaxHeap*/
void PushMaxHeap(MaxHeap h,int val){
    if(h->size==h->Capacity){
        printf("The minimum heap is full and element insertion is invalid\n");
        return;
    }
    h->data[++(h->size)]=val;
    //向上过滤
    int child=h->size;
    int parent;
    for(;child>1;child=parent){
        parent=child/2;
        if(h->data[parent]<val){
            h->data[child]=h->data[parent];
        }
        else
        {
            break;
        }
        
    }
    h->data[child]=val;
}
/*Request space for the MaxHeap*/
MaxHeap CreateMaxHeap(int MaxHeapSize){
    MaxHeap h=(MaxHeap)malloc(sizeof(MaxHeap));
    h->data=(int*)malloc((MaxHeapSize+1)*sizeof(int));
    h->size=0;
    h->Capacity=MaxHeapSize;
    return h;
}
/*Free up space for MinHeap*/
void CleanMaxHeap(MaxHeap h){
    free(h->data);
    free(h);
}
int main()
{
    MaxHeap h=CreateMaxHeap(MaxSize);

    //Construct the MaxHeap with a random array of 20 numbers, and pop the MaxHeap number in turn
    printf("Construct the MaxHeap with a random array of 20 numbers\n");
    srand((unsigned)time(NULL));
    int i=1;
    printf("20 random numbers:\n");
    for(;i<=20;i++){
        h->data[i]=getRandomNum();
        printf("%d ",h->data[i]);
        h->size++;
    }
     printf("\n");
     int realSize=h->size;//数组的真实尺寸
    BuildMaxHeap(h);
    //After the MaxHeap is established, pop the element
    /*Create a sorted array by repeatedly deleting the largest 
    element from the heap (the root of the heap) and then inserting it into the array*/
    printf("After the MaxHeap is established, pop the element:\n");
    for(i=realSize;i>0;i--){
         h->data[i]=PopMaxHeap(h);
        printf("%d ", h->data[i]);
    }
    printf("\nAfter sorting the heap, output the result of the ordered array from small to large:\n");
    for(i=1;i<=realSize;i++){
        printf("%d ",h->data[i]);
    }
    CleanMaxHeap(h);
    return 0;
}

五、测试结果:

输入输出格式说明:

  • 输入格式:

  • 输出格式:
    先输出20个随机数组的内容;
    再输出数组构造的最大堆,依次弹出的内容,来实现堆排序;

  • 测试样例1:

    输入:

    
    

    输出:

      Construct the MaxHeap with a random array of 20 numbers
      20 random numbers:
      2503 10087 8316 4624 28366 11343 11 2506 8354 14096 15705 32370 27966 16578 1005 26874 14107 31248 31125 28811
      After the MaxHeap is established, pop the element:
      32370 31248 31125 28811 28366 27966 26874 16578 15705 14107 14096 11343 10087 8354 8316 4624 2506 2503 1005 11
      After sorting the heap, output the result of the ordered array from small to large:
      11 1005 2503 2506 4624 8316 8354 10087 11343 14096 14107 15705 16578 26874 27966 28366 28811 31125 31248 32370
    
  • 测试样例2:

    输入:

    输出:

      Construct the MaxHeap with a random array of 20 numbers
      20 random numbers:
      4511 1221 17501 25194 14838 1450 13625 4472 4902 1354 23046 26691 11887 1720 17697 7431 24869 25033 10137 13027
      After the MaxHeap is established, pop the element:
      26691 25194 25033 24869 23046 17697 17501 14838 13625 13027 11887 10137 7431 4902 4511 4472 1720 1450 1354 1221
      After sorting the heap, output the result of the ordered array from small to large:
      1221 1354 1450 1720 4472 4511 4902 7431 10137 11887 13027 13625 14838 17501 17697 23046 24869 25033 25194 26691
    
  • 测试样例3:

    输入:

    输出:

      Construct the MaxHeap with a random array of 20 numbers
      20 random numbers:
      4577 19581 14336 14940 24521 14449 10338 11463 7453 9465 20088 27571 28680 4967 2788 26513 4173 321 13984 24768
      After the MaxHeap is established, pop the element:
      28680 27571 26513 24768 24521 20088 19581 14940 14449 14336 13984 11463 10338 9465 7453 4967 4577 4173 2788 321
      After sorting the heap, output the result of the ordered array from small to large:
      321 2788 4173 4577 4967 7453 9465 10338 11463 13984 14336 14449 14940 19581 20088 24521 24768 26513 27571 28680
    
  • 测试样例4:

    输入:

    输出:

      Construct the MaxHeap with a random array of 20 numbers
      20 random numbers:
      4636 16445 8211 22096 13575 19594 826 24308 9750 29872 17426 28364 1196 7889 9031 10919 28144 4295 14168 22228
      After the MaxHeap is established, pop the element:
      29872 28364 28144 24308 22228 22096 19594 17426 16445 14168 13575 10919 9750 9031 8211 7889 4636 4295 1196 826
      After sorting the heap, output the result of the ordered array from small to large:
      826 1196 4295 4636 7889 8211 9031 9750 10919 13575 14168 16445 17426 19594 22096 22228 24308 28144 28364 29872
    

六、算法分析:
最大堆的插入和删除操作都是在树的结构基础上建立的,每次的时间复杂度为O(log n)时间,
若算法需要n次插入,每次删除,则插入和删除总共的时间复杂度为O((n+m)log n);
构造有n个节点的最大堆,同理其时间复杂度为O(nlog n);
算法的空间复杂度为最大堆数据结构(以数组形式表示的树结构)的内存空间

堆排序是较稳定在排序方法,时间复杂度稳定在O(nlog n),但它的缺点是需要对数进行存储,构造最大堆后如果要得到有序的序列,
需要开辟双倍的数组内存空间,具有较高的空间复杂度,不适于大量数据的排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值