排序算法----堆排序

花了一晚上时间研究堆排序,这个排序困扰了哥很久,终于搞清楚了。

一、堆的定义

1.   父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值;

2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。


二、已知结点 i ,则它的子结点 为2*i+1 与 2*i+2 ;父节点为(i-1)/2 ;


三、堆排序

堆排序分为几个部分;

1.初始化堆; 2.输出堆顶元素 ; 3.使用最后一个元素替代堆顶元素,调整堆,循环输出;


调整结点i ,使之成为大根堆或者小根堆,算法如下:

//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2  
void AdjustHeap (int a[ ], int i, int n)  
{  
    int j, temp;  
  
    temp = a[i];  
    j = 2 * i + 1;  //左孩子下标
    while (j < n)  //向下调整,判断是否为叶子结点,调整是否结束
    {  
        if (j + 1 < n && a[j + 1] < a[j]) //若右孩子存在,找出左右孩子最小的;否则 ,在左孩子最小 
            j++;  
  
        if (a[j] >= temp)  
            break;  
  
        a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点  
        i = j;       //循环,继续向下调整
        j = 2 * i + 1;  
    }  
    a[i] = temp;  

  

堆的存储一般是线性数组;调整堆时从第一个不是叶子节点的非终端结点,即(n-1)/2开始,开始向下调整;

初始化堆的算法:

  /*
      输入:数组A,堆的大小n
     功能:建堆
   */
 void BuildHeap(int a[ ], int n)
  {
      int i;
      int begin = n/2 - 1;  //最后一个非叶子节点
      for (i = begin; i >= 0; i--){
            AdjustHeap(A, n, i);  

        }
  }


堆排序 就是将堆顶元素输出(分大根堆或者小根堆),然后堆进行调整,循环输出;算法如下:

void HeapSort(int a[ ], int n)  
{  
     
   
while (n > 1)    {

            temp = a[n-1];    //交换堆的第一个元素和堆的最后一个元素
           a[n-1] = a[0];
           a[0] = temp;
           n--;        //堆的大小减一
           AdjustHeap(A, n, 0);  //调堆

for( int i = 0 ;i <n; i++)

printf("%d  ",a[i]);//输出排序后的数组
   }

}

接下来分析下算法时间的复杂度:

初始化堆的时候:O(n)  是个复杂的公式推导,有兴趣可以自行推导

调整堆的时候:O(logn),循环调堆 复杂度:O(nlogn)

因此最好或者最坏情况下,堆排序的运行时间都是O(nlogn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值