堆排序 小结

/*
  堆排序
  利用完全二叉树的性质,将数组看成是一棵完全二叉树的顺序存储结构,
  一个完全二叉树,必有非叶结点 LEN / 2个,
  一个叶结点的根结点位置 为 Root = Child / 2
                            LChild = Root * 2
                            RChild = Root * 2 + 1


  基本排序思想:
  1.将要排序的数组创建为一个大根堆,堆顶元素为堆中最大元素。
  2.将堆顶元素,和无序区最后一个元素交换,重新调整大根堆。


  建初始堆所需的比较次数较多,堆排序不适宜于记录数较少的文件。
*/



#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define  N 11
void Swap(int *fir, int *sec);
void HeapSort(int array[], int length);
void HeapAdjust(int array[], int i, int nLength);
void SmallHeapSort(int array[], int length);
void SmallHeapAdjust(int array[], int i, int nLength);
// 大顶堆 测试
void main()
{
    int array[N + 1];
    int i;

    srand((unsigned int)time(NULL));

    //这里没有用第0号数组元素来记录数组个数,这样便于计算.
    array[0] = N;
    for (i = 1; i <= N; i++)
    {
        array[i] = rand()%90 + 10;
        printf("%4d", array[i]);
    }
    printf("/n");

    HeapSort(array, N);
//    SmallHeapSort(array, N);

    for (i = 1; i <= N; i++)
    {
        printf("%4d", array[i]);
    }
    printf("/n");
}

void HeapAdjust(int array[], int start, int end)
{

    int tmp = array[start];       //记录根节点
    int j;

    for (j = 2 * start; j <= end; j = j * 2)   //沿节点值较大的儿子向下筛选
    {
        if (j < end && array[j] < array[j + 1])  //如 RChild > LChild 则指向RChild
            j++;

        if (tmp >= array[j])   //
            break;

        array[start] = array[j];    //较大的儿子向父节点移动,更新父结点位置
        start = j;
    }
    array[start] = tmp;  //将根结点放置到最后空出的合适的位置
}
void HeapSort( int array[], int length )
{
    int i;

    // 建立大顶堆
    for ( i = length / 2 ; i > 0; i-- )
    {
        //层层调整大顶堆
        HeapAdjust( array, i, length ); 
    }
   
//     for (i = 1; i <= N; i++)
//     {
//         printf("%4d", array[i]);
//     }
//     printf("/n");

    //下面执行会很快
    for ( i = length; i > 1; i-- )
    {
        Swap(&array[1], &array[i]);       //交换至有序区
        HeapAdjust(array, 1, i-1);        //重新调整大顶堆
    }

}


//小顶堆就是堆顶放的是最小的数,交换至有序区的时候,就是递减喽

void SmallHeapSort(int array[], int length)
{
    int i;

    for (i = length / 2; i > 0; i--)
    {
        SmallHeapAdjust(array, i, length);
    }

    for (i = length; i > 1; i--)
    {
        Swap(&array[i], &array[1]);
        SmallHeapAdjust(array, 1, i - 1);
    }
}
void SmallHeapAdjust(int array[], int start, int end)
{
    int tmp = array[start],
        j;
   
    for (j = start * 2; j <= end; j *= 2)
    {
        if (j < end && array[j] > array[j + 1])
            j++;
           
        if (tmp <= array[j])
            break;
       
        array[start] = array[j];
        start = j;
    }
    array[start] = tmp;
}

void Swap(int *fir, int *sec)
{
    int t;
    t = *fir;
    *fir = *sec;
    *sec = t;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值