堆排序

                                        

                                                                             堆排序

                                      堆的介绍:

                                                       1、 堆有最大堆和最小堆之分,当父节点大于等于任何子节点时称为最大堆,当父节点小于等于任何子节点时称为最小堆;

                                                        2、堆一般用一维数组来存储的,例如对于下标为 i 的节点 它地方父节点的下标为 (i - 1)/2  它的子节点的下标为 2*i +1 ,2*i +2

                                                        注释:大堆 k[i] >= k[2*i+1]  && k[i] >= k[2*i +2] 小堆k[i] <= k[2*i+1]  && k[i] <= k[2*i +2] 

                                       算法思想:

                                               堆的创建:

                                                           1、从最后一个非叶子节点开始,进行下移操作

                                                            2、下移操作, 比较该节点与其子节点的大小,首先,比较两个子节点的大小,选下的,然后将小的与父节点进行比较;

                                                                    大数下沉;

                                                           3、堆排序操作:

                                                                     1)创建最小堆   结果是最小的在最前,最大的在最后

                                                                      2) 把堆的最后一个数与,最开始一个数进行交换

                                                                      3)打印出堆即可

                                      算法复杂度分析:

                                             1、调整堆  最好的情况是不需要调整 O(1)  最坏的情况  到最底层调整结束 高度为 h 堆 复杂度为 O(n)

                                             2、 建立堆(此部分引用他人)http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html

                                                        

  • 建堆:每一层最多的节点个数为n1 = ceil(n/(2^(h+1))),

image

因此,建堆的运行时间是O(n)。

        循环调堆:

  • 循环调堆(代码67-74),因为需要调堆的是堆顶元素,所以运行时间是O(h) = O(floor(logn))。所以循环调堆的运行时间为O(nlogn)。

总运行时间T(n) = O(nlogn) + O(n) = O(nlogn)。对于堆排序的最好情况与最坏情况的运行时间,因为最坏与最好的输入都只是影响建堆的运行时间O(1)或者O(n),而在总体时间中占重要比例的是循环调堆的过程,即O(nlogn) + O(1) =O(nlogn) + O(n) = O(nlogn)。因此最好或者最坏情况下,堆排序的运行时间都是O(nlogn)。而且堆排序还是原地算法(in-place algorithm)

                  最终可以知道 堆排序复杂度为 O(n log(n)) 


 源代码:

 

#include<iostream>
#include<cstdio>
using namespace std;

void Adjustheap(int num[], int index , int nsize)
{
    int nmin ; //标记最小的
    while(2*index + 1< nsize)   //index表示的比较的节点的位置
    {
        nmin = 2*index  + 1; // 假设左边的最小
        if(2*index + 2 < nsize )
        {//如果还有右节点 找到子节点中最小的那个 赋值给min
             if(num[nmin] > num[2*index + 2])
             {
                 nmin = 2*index  + 2;
             }
        }
        if(num[nmin] > num[index])
        {
             //如果大数在下面,那么不用下沉
             break;
        }
        else
        {//也可以用递归去做
          swap(num[index],num[nmin]);
          index = nmin;    //使新指针指向 index创建最小堆
        }

    }

}
void Printheap(char *cstring, int num[] ,int nsize )
{
    int i ;
    printf("%s", cstring);
    for(i = 0 ; i < nsize; i++)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
}
void Buildheap(int num[], int nsize)
{
    int i;
    for(i = nsize/2 -1; i >= 0; i-- )
    {
        //从最后一个不是叶子节点的位置开始建立开始过滤
        Adjustheap(num, i , nsize);
    }
    Printheap("Build Heap : ", num , nsize);
}
void HeapSort(int num[] ,int nsize )
{
    //不断的将顶元素与底部元素进行交换, 然后进行下沉操作
    int length;
    int i;
    length  = nsize;
    Printheap("Before sort: ", num ,  nsize);
    Buildheap(num, nsize);      //建立堆后最后一个会是最大,第一个会是最小
    for(i = length -1; i >= 0; i--)
    {
        swap(num[i],num[0]);   //每次交换顶元素和最后一个
        nsize --;                 //将最小的换到最后,规模减一
        Adjustheap(num,0, nsize);

    }
    Printheap("After Heap: ", num , length);
}
int main()
{
   int data[] = {6,4,1,2,8,4,7,3,0,9};
   HeapSort(data, 10);

   return  0;
}

                               

wangxiaoming CSDN认证博客专家 架构 Spring Boot Redis
博客是很好的总结和记录工具,如果有问题,来不及回复,关注微信公众号:程序员开发者社区,获取我的联系方式,向我提问,也可以给我发送邮件,联系 1275801617@qq.com
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付 19.89元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值