zoukankan      html  css  js  c++  java
  • 关于heap的两三事

    以下code 来源于 啊哈磊大神~ =-=

    你可以百度  --- 啊哈磊 ---

    都是 关于heap的一些操作...

    向下调整:->

     1 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整 
     2 {
     3     int t,flag=0;//flag用来标记是否需要继续向下调整
     4     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
     5     while( i*2<=n && flag==0 )
     6     {       
     7         //首先判断他和他左儿子的关系,并用t记录值较小的结点编号
     8         if( h[ i] > h[ i*2] )
     9             t=i*2;
    10         else
    11             t=i;
    12         //如果他有右儿子的情况下,再对右儿子进行讨论
    13         if(i*2+1 <= n)
    14         {
    15             //如果右儿子的值更小,更新较小的结点编号 
    16             if(h[ t] > h[ i*2+1])
    17                 t=i*2+1;
    18         }
    19         //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的 
    20         if(t!=i)
    21         {
    22             swap(t,i);//交换它们,注意swap函数需要自己来写
    23             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
    24         }
    25         else
    26             flag=1;//则否说明当前的父结点已经比两个子结点都要小了,不需要在进行调整了
    27     }
    28 }
    View Code

    向上调整:->

     1 void siftup(int i) //传入一个需要向上调整的结点编号i
     2 {
     3     int flag=0; //用来标记是否需要继续向上调整
     4     if(i==1)  return; //如果是堆顶,就返回,不需要调整了   
     5     //不在堆顶 并且 当前结点i的值比父结点小的时候继续向上调整
     6     while(i!=1 && flag==0)
     7     {
     8         //判断是否比父结点的小
     9         if(h[ i]<h[ i/2])
    10             swap(i,i/2);//交换他和他爸爸的位置
    11         else
    12             flag=1;//表示已经不需要调整了,当前结点的值比父结点的值要大
    13         i=i/2; //这句话很重要,更新编号i为它父结点的编号,从而便于下一次继续向上调整 
    14     }
    15 }
    View Code

    的确 很 易懂

    两种方式对元素 进行堆排序:->

     1 #include <stdio.h>
     2 int h[ 101];//用来存放堆的数组
     3 int n;//用来存储堆中元素的个数,也就是堆的大小
     4 
     5 
     6 //交换函数,用来交换堆中的两个元素的值
     7 void swap(int x,int y)
     8 {
     9     int t;
    10     t=h[ x];
    11     h[ x]=h[ y];
    12     h[ y]=t;
    13 }
    14 
    15 
    16 //向下调整函数
    17 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整
    18 {
    19     int t,flag=0;//flag用来标记是否需要继续向下调整
    20     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
    21     while( i*2<=n && flag==0 )
    22     {        
    23         //首先判断他和他左儿子的关系,并用t记录值较小的结点编号
    24         if( h[ i] > h[ i*2] )
    25             t=i*2;
    26         else
    27             t=i;
    28         //如果他有右儿子的情况下,再对右儿子进行讨论
    29         if( i*2+1 <= n)
    30         {
    31             //如果右儿子的值更小,更新较小的结点编号  
    32             if(h[ t] > h[ i*2+1])
    33                 t=i*2+1;
    34         }
    35         //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的  
    36         if(t!=i)
    37         {
    38             swap(t,i);//交换它们,注意swap函数需要自己来写
    39             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
    40         }
    41         else
    42             flag=1;//则否说明当前的父结点已经比两个子结点都要小了,不需要在进行调整了
    43     }
    44 }
    45 
    46 
    47 //建立堆的函数
    48 void creat()
    49 {
    50     int i;
    51     //从最后一个非叶结点到第1个结点依次进行向上调整
    52     for(i=n/2;i>=1;i--)
    53     {
    54         siftdown(i);
    55     }  
    56 }
    57 
    58 
    59 //删除最小的元素
    60 int deletemin()
    61 {
    62     int t;
    63     t=h[ 1];//用一个临时变量记录堆顶点的值
    64     h[ 1]=h[ n];//将堆得最后一个点赋值到堆顶
    65     n--;//堆的元素减少1
    66     siftdown(1);//向下调整
    67     return t;//返回之前记录的堆得顶点的最小值
    68 }
    69 
    70 
    71 int main()
    72 {
    73     int i,num;
    74     //读入数的个数
    75     scanf("%d",&num);
    76 
    77 
    78     for(i=1;i<=num;i++)
    79         scanf("%d",&h[ i]);
    80     n=num;   
    81 
    82     //建堆
    83     creat();
    84 
    85     //删除顶部元素,连续删除n次,其实也就是从小到大把数输出来
    86     for(i=1;i<=num;i++)
    87         printf("%d ",deletemax());
    88     getchar();
    89     getchar();
    90     return 0;
    91 }
    View Code
     1 #include <stdio.h>
     2 int h[ 101];//用来存放堆的数组
     3 int n;//用来存储堆中元素的个数,也就是堆的大小
     4 
     5 
     6 //交换函数,用来交换堆中的两个元素的值
     7 void swap(int x,int y)
     8 {
     9     int t;
    10     t=h[ x];
    11     h[ x]=h[ y];
    12     h[ y]=t;
    13 }
    14 
    15 
    16 //向下调整函数
    17 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整
    18 {
    19     int t,flag=0;//flag用来标记是否需要继续向下调整
    20     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
    21     while( i*2<=n && flag==0 )
    22     {        
    23         //首先判断他和他左儿子的关系,并用t记录值较大的结点编号
    24         if( h[i] < h[i*2] )
    25             t=i*2;
    26         else
    27             t=i;
    28         //如果他有右儿子的情况下,再对右儿子进行讨论
    29         if( i*2+1 <= n)
    30         {
    31             //如果右儿子的值更大,更新较小的结点编号  
    32             if(h[t] < h[ i*2+1])
    33                 t=i*2+1;
    34         }
    35         //如果发现最大的结点编号不是自己,说明子结点中有比父结点更大的  
    36         if(t!=i)
    37         {
    38             swap(t,i);//交换它们,注意swap函数需要自己来写
    39             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
    40         }
    41         else
    42             flag=1;//则否说明当前的父结点已经比两个子结点都要大了,不需要在进行调整了
    43     }
    44 }
    45 
    46 
    47 //建立堆的函数
    48 void creat()
    49 {
    50     int i;
    51     //从最后一个非叶结点到第1个结点依次进行向上调整
    52     for(i=n/2;i>=1;i--)
    53     {
    54         siftdown(i);
    55     }  
    56 }
    57 
    58 
    59 //堆排序
    60 void heapsort()
    61 {
    62     while( n>1 )
    63     {
    64         swap(1,n);
    65         n--;
    66         siftdown(1);
    67     }
    68 }
    69 
    70 
    71 int main()
    72 {
    73     int i,num;
    74     //读入n个数
    75     scanf("%d",&num);
    76 
    77 
    78     for(i=1;i<=num;i++)
    79         scanf("%d",&h[ i]);
    80     n=num;   
    81 
    82 
    83     //建堆
    84     creat();
    85 
    86 
    87     //堆排序
    88     heapsort();
    89 
    90 
    91     //输出
    92     for(i=1;i<=num;i++)
    93         printf("%d ",h[i]);
    94 
    95     getchar();
    96     getchar();
    97     return 0;
    98 }
    View Code


    // 这里的 swap 使用 引用传递形参值 更好

    真正理解一个东西  你可以将它以很简单的方式 讲解出来~

    just follow your heart
  • 相关阅读:
    CODING x 百果园 _ 水果零售龙头迈出 DevOps 体系建设第一步
    Nocalhost 亮相 CD Foundation 国内首届 Meetup,Keith Chan 将出席致辞
    做云原生时代标准化工具,实现高效云上研发工作流
    打造数字化软件工厂 —— 一站式 DevOps 平台全景解读
    WePack —— 助力企业渐进式 DevOps 转型
    CODING Compass —— 打造行云流水般的软件工厂
    Nocalhost —— 让云原生开发回归原始而又简单
    CODING 代码资产安全系列之 —— 构建全链路安全能力,守护代码资产安全
    Nocalhost:云原生开发新体验
    使用 Nocalhost 开发 Kubernetes 中的 APISIX Ingress Controller
  • 原文地址:https://www.cnblogs.com/radical/p/3793594.html
Copyright © 2011-2022 走看看