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

  }
*/
相关推荐
jz_ddk5 分钟前
[实战]调频(FM)和调幅(AM)信号生成(完整C语言实现)
c语言·算法·信号处理
CloudAce云一21 分钟前
谷歌云代理商:谷歌云TPU/GPU如何加速您的AI模型训练和推理
算法
轻语呢喃1 小时前
每日LeetCode : 杨辉三角
javascript·后端·算法
YuTaoShao1 小时前
【LeetCode 热题 100】148. 排序链表——(解法二)分治
java·算法·leetcode·链表
Shilong Wang2 小时前
三维旋转沿轴分解
算法·计算机视觉·机器人
ygming2 小时前
Q43- code973- 最接近原点的 K 个点 + Q44- code347- 前 K 个高频元素
前端·算法
lightqjx2 小时前
【数据结构】顺序表(sequential list)
c语言·开发语言·数据结构·算法
ygming2 小时前
Hashmap/ Hashset- Q39~Q42内容
前端·算法
蒟蒻小袁3 小时前
力扣面试150题--全排列
算法·leetcode·面试
mit6.8243 小时前
[Backlog] 核心协调器 | 终端用户界面(TUI)实现 | 多分支任务冲突解决 | 测试验证体系
人工智能·算法