堆排序算法代码实现

对排序算法的核心思想是:

把一个数组按照完全二叉树创建好最大堆以后,拿堆顶元素和最后一个元素(数组)的最后一个元素)交换以后,

对于这个新的数组,除去最后面那个最大的元素(原先的堆顶元素), 剩余子序列再次调整成最大堆。

如此反复交换最大堆堆顶元素,调整剩余子序列到最大堆。

直到最后子序列就剩下一个元素的时候,排序也就完成了。我们就得到了这个数组从小到大的排列结果。

堆排序算法的代码实现稍微复杂,需要多画图,多理解

在上一节创建初始堆的基础上,堆排序算法实现代码如下:

#include <stdio.h>
void PrintArray(int b[],int n)
{
 int i;
 for(i=0;i<n;i++)
 printf("%d ", b[i]);
}
void CreateHeap(int b[], int i, int len)
{
  int temp,j;
  /*当前结点看作一个父结点,先把它的值存储到临时变量,
  *防止交换过程中父亲结点的值被覆盖掉
  */
  temp = b[i];
  for(j=2*i+1;j<len;j=2*j+1)
  {
    /*如果左孩子(a[j])比右孩子(a[j+1])小
     *就比较右孩子和父亲结点a[i]
     *否则就比较左孩子和父亲结
     */
    if(j<len-1 && b[j]<b[j+1])
    {
      ++j;
    }
    if(temp>=b[j])
    {
      break;
    }
     /*父结点比孩子结点小,把较大的孩子结点值赋给父亲结点
      *并记住较大的孩子结点下标
      */
      b[i]=b[j];
     /*如果循环不结束,下次将以这次下标为j的元素为父结点和这个父结点的左右子元素比较
      *如果循环比较结束,循环最外层将会把父亲结点的最小值赋给子结点中最大
      */
      i=j;
   }
   /*此处其实是把父结点的旧值赋给值最大的那先前子结点*/
   b[i]=temp;
}
void InitHeap(int a[],int arr_len)
{
  int i;
  for(i=(arr_len-1)/2;i>=0;i--)
  {
    CreateHeap(a, i, arr_len);
  }
}
void HeapSort(int a[],int arr_len)
{
  InitHeap(a, arr_len);
  printf("初始最大堆:");
  PrintArray(a, arr_len);
  printf("\n");
  int i,temp;
  for(i=arr_len-1;i>0;i--)
  {
    temp = a[i];
    a[i] = a[0];
    a[0] = temp;
    /*从根结点(0代表从根结点,原始最大堆末尾原素现在变成第一个元素)
     *上开始逐次往下调整堆为最大堆
     *每次从最大堆换到末尾的那个元素,下次调整时不算在内,所以用递减的i
     *当最后剩一个a[0]为结点时就没必要再调整了,此时a[0]就是最小的
     */
     printf("第%d次堆排序结果:",(arr_len-i));
     CreateHeap(a, 0, i);
     PrintArray(a, arr_len);
     printf("\n");
   }
}
int main()
{
  int a[]={10,50,32,5,76,9,40,88};
  int arr_len = sizeof(a)/sizeof(a[0]);
  HeapSort(a, arr_len);
  printf("堆排序的最终结果:");
  PrintArray(a, arr_len);
  return 0;
}

代码运行结果:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值