笔记: 排序算法——堆排序(C++实现)

  1. 堆排序
    简单介绍:具有空间原址性(即进行原址排序,任何时候都只需要常数个额外的元素空间存储临时数据)。二叉堆是一个数组,近似可以看成一个完全二叉树,可分为最大堆和最小堆。在堆排序中,采用的是最大堆,其性质是:除了根节点以外的所有节点i都满足父节点>子节点。而最小堆常用来构造优先队列。
    时间复杂度:时间复杂度 Θ ( n lg ⁡ n ) \Theta(n \lg n) Θ(nlgn)

  2. 堆排序的伪代码(截图于算法导论)
    a) max_heapify: 用于维护堆性质,其时间复杂度是 O ( lg ⁡ n ) O(\lg n) O(lgn)
    max_heapify
    b) build_max_heap: 将输入数组构造成一个最大堆,其时间复杂度是线性的.
    build_max_heap
    c) heap_sort: 对输入数组进行原址排序,其时间复杂度是 O ( n lg ⁡ n ) O(n \lg n) O(nlgn)
    heapsort

  3. C++实现(需要注意的是,C++数组的起始标号是0,而上述算法中数组的起始是1)

/**
堆排序  2020.04.20
Author: 豆奶
Reference: 算法导论第三版
 **/

#include <iostream>
using namespace std;

/**
定义max_heapify函数去维护最大堆的性质,即保证父节点的值大于子节点的值
Input:
	A[]: int[], 待排序的数组. 指针传递,函数内部对A的修改能导致外部A的变化
	i: int, 需要维护堆性质的子堆.
	length: int,是待排序数组的长度.
Output:
	A: int*, 排序后的数组.
  **/
void max_heapify( int A[], int i, int length){
	int l = 2*i+1;  // i的左子节点
	int r = 2*i+2;
	int largest;	// i, l, r中,在A中值最大的索引
	if (l<length && A[l]>A[i])
		largest = l;
	else
		largest = i;
	if (r<length && A[r]>A[largest])
		largest = r;
	// 如果最大那个数的索引不是i,则交换值使得i是最大值的索引
	if (largest != i){  
		int temp = A[i];
		A[i] = A[largest];
		A[largest] = temp;
		max_heapify(A, largest, length); // 对交换后的largest堆进行调整
	}
}

/**
定义buidl_max_heap函数去建立最大堆
Input:
	A[]:int[],是需要排序的数组.
	length: int,是待排序数组的长度.
  **/
void buidl_max_heap(int A[], int length){
	for(int i = int(length/2)-1; i>=0; i--)
		max_heapify(A, i, length);
}

/**
定义heap_sort函数实现堆排序
Input:
	A[]:int[],是需要排序的数组.
	length: int,是待排序数组的长度.
Output(不需要return):
	A: int*, 排序后的数组.
  **/
void heap_sort(int A[], int length){
	buidl_max_heap(A, length);
	for(int i=length-1; i>0; i--){
		int temp = A[0];
		A[0] = A[i];
		A[i] = temp;
		length = length -1;
		max_heapify(A, 0, length);
	}
}
  1. 测试
int main(){
	int A[15] = {3, 19, 13, 5, 6, 28, 33, 38, 43, 12, 53, 58, 63, 2, 73};
	int i;

	cout<<"A[i]的值为:  ";
	for(i=0; i<15; i++){
		cout<<A[i]<<", ";
	}
	cout<<endl;

	int length = sizeof(A)/sizeof(A[0]);  
	//sizeof()函数可以返回数组所占的内存,而sizeof(A[0])返回的是数组第一个元素所占的内存。

	heap_sort(A, length);

	cout<<endl<<"排序后A[i]的值为:  ";
	for(i=0; i<15; i++){
		cout<<A[i]<<",  ";
	}
	cout<<endl<<endl;
	return 0;
}
  1. 参考文献
  • 算法导论(第三版)
  • 麻省理工学院:算法导论 (视频)

如有不对之处,还望指出.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值