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
  • 相关阅读:
    ES基础(五十五)在私有云与公有云上管理与部署 Elasticsearch 集群
    ES基础(五十四)如何对集群进行容量规划
    ES基础(五十二)Hot & Warm 架构与 Shard Filtering
    ES基础(四十九)集群内部安全通信
    ES基础(四十八)集群身份认证与用户鉴权
    kata + docker run & star
    libcontainer nsexec + unshare + syscall(SYS_setns
    docker createHooks
    mount namespace
    exec.Command("/proc/self/exe", "child")
  • 原文地址:https://www.cnblogs.com/radical/p/3793594.html
Copyright © 2011-2022 走看看