1.Sift-up函数  假定对于某个i>1 A[i]的键值大于父亲节点的键值 此时A[i]的辈分就高了   也就是需要向上调整A[i]  让原来A[i]的父亲下来当儿子 

int Siftup(int *A,int i)
{    
    int temp=A[i];
    while(i>=2&&temp>A[i/2])
    {
        A[i]=A[i/2];
        i=i/2;
    }
    A[i]=temp;
}

该过程类似于 插入排序 为每一个A[i]确定合适位置 其余的往后移

 

2.Sift-down函数 假定对于某个父亲节点i  A[i]的键值小于了孩子节点的键值 此时就需要向下调整这个父亲节点,降低它的辈分

int Siftdown(int *A,int i,int length)
{    int temp=A[i];
    int j;
    while(2*i<=length)
    {
        if(2*i+1<=length&&A[2*i+1]>A[2*i])    j=2*i+1;
        else    j=2*i;
        if(temp<A[j])
            A[i]=A[j];
        else
            break;
        i=j;
    }
    A[i]=temp;
}

解释:1.函数参数有三个 分别是数组A 要调整的节点i 数组A的大小 

  2.while循环条件是 该节点非叶节点,也就是有子节点,也就是该节点有左子树

  

 3.Insert插入函数

int Insert(int* A,int x,int* length)
{
    (*length)++
    A[*length]=x;
    Siftup(A,*length);
}

4.Delete删除函数

int Delete(int* A,int i,int *length)
{    
    int x=A[i];
    int y=A[*length];
    (*length)--;
    A[i]=y;//用y替换它 
    if(y>x) 
        Siftup(A,i);
    else
        Siftdown(A,i,*length);
}

思路是用 堆中最后一个元素替换要删除的节点i ,替换之后产生的结果是,节点i处可能不再符合堆的定义,而除了节点i以外仍旧为堆。因此,此时需要调整,调整的情况有两种,如果y大于x,那么需要向上调整,看看是否辈分会提高;如果y小于x,那么需要向下调整,看看是否会降低辈分。

5.创建堆

int Makeheap(int* A,int length)
{
    for(int i=length/2;i>=1;i--)
    {
        Siftdown(A,i,length); 
    }
}

创建堆的过程,是从第一个非叶子节点,向下调整。 如果令C(n)表示该算法的元素比较次数,则比较次数范围是在[n-1,4n) 也就是 sitar(n)的时间内完成了堆的创建。

6.堆排序

int HeapSort(int *A,int length)
{
    Makeheap(A,length);
    for(int i=length;i>=2;i--)
    {
        int temp;
        temp=A[i];
        A[i]=A[1];
        A[1]=temp;
        length=length-1;
        Siftdown(A,1,length);
    }

该过程首先建堆,此时A【1】即为最大值,与最后一个元素交换,即确定了最大元素的值;然后该元素就不用再管它了;因为咱们是与第一个元素进行了交换,所以第一个元素可能不再符合堆的定义,而其它节点仍旧符合堆的定义,所以,我们采用Siftdown调整A【1】使其仍然为堆;调整为堆后的A【1】又变成了新的堆的最大值,再重复上述操作:交换、调整A【1】使其仍然为堆……

使用makeheap是在sitar(n)范围内的算法,for循环一共进行了 length-1次,每次for循环内部都会进行Siftdown操作,Siftdown操作是O(logn)级别的。因此,该算法时间复杂度为O(nlogn)