蓝桥杯算法基础(15):十大排序算法(堆排序)c语言版

堆排序

外堆:
需要一段和原来数组长度大小的内存空间,这段内存空间是用来存储堆结构的
内堆:
不需要重新申请内存,直接原来的数组上进行排序

堆结构
本质上就是一个完全二叉树(不了解二叉树可以取学习一下二叉树的基本概念),每一个节点的存储都是连续的

知道当前下标为current
    从0开始计数
    左子树下标-->2*current+1
    右子树下标-->2*current+2

    从1开始计数
    左子树下标-->2*current
    右子树下标-->2*current+1

    大顶堆
    父亲的权值比左右子树的权值大
    小顶堆
    父亲的权值比左右子树的权值小

    (小顶堆)
             2
            / \
           3   4
          /\   /
         8  7 6
   (大顶堆)
              8
             /\
            7  3
           /\  /\
          3 5 2  0
         /
        2
        完全二叉树中间是不能有空的
        (以下二叉树就不是完全二叉树)
              8
             /\
            7  3
           /\  /\
          3 5 2  0
         /   \
        2     4

堆结构 

//外堆
typedef struct Heap{
 int* root;
 int length;
}Heap;

 (伪代码)

//入堆
void pushHeap(Heap* heap,int data);
//出堆
int popHeap(Heap* heap);

 
arr[MAXSIZE];
for(arr){
pushHeap(heap,arr[i])
}
for(heap){
arr[i]=popHeap(heap);
}

 创建一个堆

Heap* creatHeap(int length){
Heap* heap=(Heap*)malloc(sizeof(Heap)*length);//开辟一个较大的内存空间
 assert(heap);//断言一下
 heap->length=0;//让length从0开始
 heap->root=(int*)malloc(sizeof(int)*length);//开辟length长度的int数组,表示各个节点节点
 assert(heap->root);
 return heap;

}

 

  //5 74 94 12 60 33 14
  小顶堆
  每拿一个数,放到底部,每次都要与父亲比较,小于父亲则与父亲替换
            5(0)
           /     \
          12(1)   14(2)
         / \       /  \
       74(3)60(4)94(5)33(6)
   //入堆
  // 0 1 2 3 4 5 6 7 8
  void pushHeap(Heap* heap,int data){
       int current=heap->length++;
       int parent=(current-1)/2;
       heap->root[current]=data;
       while(parent!=current){
           if(heap->root[current]<heap->root[parent]){
           swap(heap->root,current,parent);
           current=parent;
           parent=current/2;
           }else
           break;
       }
   }

  拿走一个最小值,最后一个到第一个位置,再与左右子结点中比它小且二者中比较小的交换,直到回到再次满足小顶堆
            33
           /  \
          12   14
         / \    /
       74  60 94

            12
           /  \
          33   14
         / \    /
       74  60 94
       //出堆
  int popHeap(Heap* heap){
       int val=heap->root[0];//   拿走一个最小值
       int  current=0;//从第一个位置开始
       int rchild=2*current+2;//右子树(rchild-1为左子树)
       int small;
       int n=--heap->length;//最后一个位置
       heap->root[0]=heap->roo[--heap->length];//将最后的数放到第一个位置上
       while(rchild <= heap->length){
           small=arr[rchild-1]<arr[rchild]?richild-1:rchild;
           if(heap->root[small]<heap->root[current]){
           swap(heap->root,small,current);//heap->root是一个指针开辟空间形成的数组
           current=small;
           rchild=2*(current)+2;
           }
       }else
           break;
       return val;
  }



  viod heapSort(int arr[],int length){
  Heap *heap=creatHeap(MAXSIZE);
   for(int i=0;i<MAXSIZE;i++){
   pushHeap(heap,arr[i]);

   }

   for(inti=0;i<MAXSIZE;i++){
   arr[i]=popHeap(heap);}

   free(heap->root);

  }



  内堆实现
  //不需要重新申请空间
   heapify实现大顶堆
   再将大顶堆的最大值逐渐放到最后一位上
   最终实现从小到大有序的小顶堆


       //heapify 堆化
   void  heapify(int arr[],int length,int current){
   int rchild=2*current+2;
   int large;
       while(rchild<=length){
           //若右子节点为length位置上的,然而length位置上没有元素,则意味着只有左子节点,在length-1上
           //选子节点较大的元素
           large=rchild==length?rchild-1:(arr[rchild-1]>arr[rchild]?rchild-1:rchild);

           if(arr[large]>arr[current]){
           swap(arr,large,current);//与比自己大的子节点交换,并更新位置,继续与子节点比较,直至找到合适的位置
           current=large;
           rchild=2*current+2;
           }else
           break;//如果找到合适的位置,则推出循环
           //堆化就是将某一个位置的数按照大顶堆的方式,找到合适的位置
       }
   }
  void heapSort2(int arr[],int length){
       int current=length/2;//将除完全二叉树最后一层的叶子节点的数进行堆化
       while(current>=0)//直到所有的数都完成堆化,则结束
       {
           heapify(arr,length,current);
           current--;

       }



       showArr(arr,length);//输出arr所有元素


       while(length>=0){
        swap(arr,0,--length);//逐渐将大顶堆的最大值放到数组的后面,将最后一个数放到第一个位置
        heapify(arr,length,0);
        //然后对第一个位置上的数进行堆化,每次循环,length都减1,就把之前放到最后的最大值,给踢出对结构了,如此最大值便保留了下来,如此循环直到所有数都排好序
       //形成从小到大的序列。
       }

  }
*/

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-21 12:48:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-21 12:48:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-21 12:48:01       87 阅读
  4. Python语言-面向对象

    2024-03-21 12:48:01       96 阅读

热门阅读

  1. 量化交易入门(十)Python开发-异常处理

    2024-03-21 12:48:01       42 阅读
  2. python图形化编程pygame游戏模块

    2024-03-21 12:48:01       35 阅读
  3. 八大排序算法之快速排序

    2024-03-21 12:48:01       43 阅读
  4. 面试宝典:解决MySQL主从不一致的策略

    2024-03-21 12:48:01       39 阅读
  5. React面试总结

    2024-03-21 12:48:01       42 阅读
  6. C++:指针 引用 普通变量适用场景

    2024-03-21 12:48:01       44 阅读
  7. NodeJs接入腾讯云存储COS

    2024-03-21 12:48:01       40 阅读
  8. 机器学习:随机森林算法

    2024-03-21 12:48:01       43 阅读
  9. webpack从零开始搭建vue项目

    2024-03-21 12:48:01       88 阅读
  10. Python实战:Pandas数据合并与重塑

    2024-03-21 12:48:01       44 阅读