算法导论复习与实践(三):堆排序

堆排序(heapsort)是一种原地排序,任何时候数组中只有常数个元素存储在输入数组以外,运行时间复杂度O( n log(n) )。堆数据结构是一种数组对象,可视为一棵完全二叉树,树中每个节点与数组中存放该节点值的那个元素对应,除最后一层外,树的每一层都是填满的。堆排序过程涉及以下相关操作:计算某个节点的父节点,计算某个节点的左子节点,计算某个节点的右子节点,维护堆的性质,建堆,堆排序。维护...
摘要由CSDN通过智能技术生成

堆排序(heapsort)是一种原地排序,任何时候数组中只有常数个元素存储在输入数组以外,运行时间复杂度O( n log(n) )。
堆数据结构是一种数组对象,可视为一棵完全二叉树,树中每个节点与数组中存放该节点值的那个元素对应,除最后一层外,树的每一层都是填满的。
堆排序过程涉及以下相关操作:计算某个节点的父节点,计算某个节点的左子节点,计算某个节点的右子节点,维护堆的性质,建堆,堆排序。

维护最大堆性质:当某个节点的值小于其左或右子节点时,违反了最大堆性质时,让该节点的值在最大堆的树中”下降“,比较该节点与左右子节点,让其与最大的子节点的值交换,然后递归调用维护最大堆性质的函数维护该节点的最大子节点的最大堆性质直到堆的数据结构不再有任何变化。

建堆:在堆的树结构中,下标为(n/2+1)~n中的元素都是树中的叶子节点,都可看成只有一个元素的堆,然后对其他节点自大至小都调用一遍维护最大堆性质函数即可完成建堆过程。

堆排序:首先进行建堆,然后每次交换堆中最后一个元素与堆的根元素,最后维护根元素的最大堆性质,直到堆中只剩一个元素即完成完成排序过程

具体代码实现如下:

#include <assert.h>
#include <stdio.h>
#include <iostream>

//计算父节点
int Parent(const int i){
  assert( i >= 0 );
  return (i-1)/2;
}
//计算左子节点
int Left(const int i){
   assert( i >= 0 );
  return 2*i+1;
}
//计算右子节点
int Right(const int i){
  assert( i >= 0 );
  return 2*i+2;
}
//维护最大堆性质
void MaxHeapify(int* data, const int heap_size, const int i){
  assert( data != NULL );
  assert( i >= 0 );
  assert( i < heap_size );
  
  int left = Left( i );
  int right = Right( i );
  int largest = 0;
  if( (left < heap_size) && (data[ left ] > data[ i ] ) ){
    largest = left;
  }
  else{
    largest = i;
  }

  if( (right < heap_size) && (data[ right ] > data[ largest ]) ){
    largest = right;
  }

  if( largest != i){
    int temp = data[ i ];
    data[ i ] = data[ largest ];
    data[ largest ] = temp;
    MaxHeapify( data, heap_size, largest );
  }
}
//建堆
void BuildMaxHeap(int *data, const int length){
  assert( data != NULL );
  assert( length > 0 );
  
  int heap_size = length;
  for( int i = (length/2 - 1); i >=0; --i){
    MaxHeapify(data, heap_size, i);
  }
}
//堆排序
void HeapSort(int *data, const int length)
{
  assert( data != NULL );
  assert( length > 0 );
  
  int heap_size = length;
  BuildMaxHeap(data, length);
  for( int i = length - 1; i > 0; --i){
    int temp = data[ 0 ];
    data[ 0 ] = data[ i ];
    data[ i ] = temp;

    heap_size--;
    MaxHeapify(data, heap_size, 0);
  }
}

int main()
{
  int data[]={4,1,3,2,16,9,10,14,8,7};

  std::cout<<"Before: ";
  for(auto d : data){
    std::cout<<d<<"  ";
  }
  std::cout<<std::endl;

  Heap::HeapSort(data, 10);

  std::cout<<"After: ";
  for(auto d : data){
    std::cout<<d<<"  ";
  }
  std::cout<<std::endl;

  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值