堆排序的代码思路

堆排序

第一步 —— 建堆

我们采用向下调整建堆的方式

void AdjustDown(int* a, int n, int parent) // a:数组名; n;数组元素个数; parent:从这个位置开始调整
{
    //如何向下调整建堆?以建立大堆为列子
    //向下调整是有一个前提得,它认为它的左子树和右子树都是堆,然后递归下去,找到左孩子和右孩子当中大的那个,与之交换
     //我们开始吧,首先要找到左孩子与右孩子当中大的那个
     //我们用的假设法,假设左孩子大
    int child = (parent*2 ) + 1; //根据父母找孩子:parent*2 + 1
    
    
    while(child < n)  //循环是为了将位置一直调整下去,因为你下面的代码只调整了一次位置
    {
        
        
        
        if(child+1 < n && a[child+1] > a[child]) //如果右孩子大于左孩子,就换成右孩子, 但是这里的child+1可能有越界的风险
    {                         //因为数组可能只有child个元素,所以我们要加上限制条件:child+1 < n
        ++child; 
    }
    
    //再比较最大的那个孩子与父亲的大小,根据需要调整位置
    if(a[child] > a[parent])
    {
        Swap(&a[child], &a[parent]); //不要忘了加&;
        parent = child;      //调整了之后,要更新位置	
        child = parent*2+1;
    }
    else   //如果不是的话那就不用调整,直接跳出
    {
        break; 
    }
    
}
        
        
        
        
    }
    

第二步——排序

void HeapSort(int *a, int n)
{
    //叶子节点不用调,因为叶子节点就它本身一个数据,所以不用调,我们从倒数第一个非叶子节点处开始调整
    //倒数第一个非叶子节点就是最后一个叶子节点的父亲,我们可以通过这个公式来找到他:(n-1) / 2 ,n是最后一个节点的下标, 但是本题的n表示的是数据的个数,所以下标是:n-1; 这个时候公式就变成了:(n-1-1)/ 2
    for(int i = (n-1-1)/2; i >= 0; i--)
    {
        //开始调整
        AdjustDown(a, n, i); //从i这个位置开始调整
        //我们是升序排列 所以我们要建立大堆
        
    }
    
    //大堆建立完成之后,根据堆排序的算法思想: 把堆顶元素与堆尾元素交换, 然后再把堆尾的那个元素隔离出去
    // 因此 堆尾会变化,我们要重新定义一个堆尾变量
    int end = n - 1;
    whlie(end > 0)
    {
        Swap(&a[0], &a[end]); //堆顶与堆尾交换
        AdjustDown(a, end, 0); //重新调整,把堆尾排除在外
        end--;                //更新end的位置	
    }
    
    
    
    
    
}

你可能感兴趣的:(算法)