蓝桥杯算法基础(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,就把之前放到最后的最大值,给踢出对结构了,如此最大值便保留了下来,如此循环直到所有数都排好序
       //形成从小到大的序列。
       }

  }
*/
相关推荐
木木子2213 分钟前
# 密码强度检测深度解析:正则表达式实时分析、多维度评分算法与可视化反馈
mysql·算法·华为·正则表达式·harmonyos
Sw1zzle3 小时前
算法入门(四):二叉树 - 递归遍历三件套
算法·leetcode
万法若空4 小时前
【算法-查找】查找算法
java·数据结构·算法
海石4 小时前
子树怎么找?树的3种遍历方式来帮忙!
算法·leetcode
海石4 小时前
难度分 1588:思路 + 技巧 = AC
算法·leetcode
珠海西格电力7 小时前
云边端协同架构:零碳园区管理系统的技术底座
大数据·运维·人工智能·算法·架构·能源
还有多久拿退休金9 小时前
让飞书知识库跟着 commit 自己长:一套自动化知识库的真实实现
前端·算法·架构
KaMeidebaby10 小时前
卡梅德生物技术快报|小 RNA 适配体合成 + 多方法亲和力表征全流程标准化操作手册
前端·网络·数据库·人工智能·算法
是Dream呀10 小时前
基于深度学习的人类行为识别算法研究
人工智能·深度学习·算法
happyprince11 小时前
03_NVIDIA_ModelOpt-量化算法深入
人工智能·深度学习·算法