堆排序的实现 - C语言

🚩 堆排序

定义

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。除了最低级别外所有级别都满了,如果最低级别未满,则必须将节点打包到左侧


二叉堆的性质

给定一个节点数为n,高度为h的二叉堆

  • n ∈ [ 2 h , 2 h + 1 − 1 ] n \in [2^h, 2^{h+1} -1] n[2h,2h+11]
  • 高度 h = O ( l o g ( n ) ) h = O(log(n)) h=O(log(n))

数组实现二叉堆

i i i 处有一个节点 x x x

  • 左孩子在 2 i + 1 2 i+1 2i+1
  • 右孩子在 2 i + 2 2 i+2 2i+2
  • 父节点在 ( i − 1 ) / 2 (i-1)/2 (i1)/2
    在这里插入图片描述

大堆

子结点的键值或索引总是小于它的父节点
在这里插入图片描述

小堆

子结点的键值或索引总是大于它的父节点在这里插入图片描述

大堆的建立

在这里插入图片描述小堆建立同理


deleteMax

使用A[n-1]代替A[0], 然后与下面的节点比较,往下交换位置,满足大顶堆性质即可
在这里插入图片描述deleteMin同理



🚩 C语言的实现

1. 大堆的建立

bool InsertMax(int *A, int size, int x){
	int hole = size++;
	while (hole > 0 && x > A[(hole - 1)/2]){  // compare the node to its parent
		A[hole] = A[(hole - 1) / 2];  // change the location of the nodes
		hole = (hole - 1) / 2;
	}
	A[hole] = x;  // assign the correct location to x
	return true;
}

2. 小堆的建立

bool InsertMin(int *A, int size, int x){
	int hole = size++;
	while (hole > 0 && x < A[(hole - 1) / 2]){  // compare the node to its parent
		A[hole] = A[(hole - 1) / 2];  // change the location of the nodes
		hole = (hole - 1) / 2;
	}
	A[hole] = x;  // assign the correct location to x
	return true;
}

3. deleteMax

int deleteMax(int *A, int size){
	if (size == 0){  // the heap is empty
		return -1;
	}
	int max = A[0];
	int hole = 0;
	int x = A[--size];

	// percolate down
	while (2 * hole + 1 < size){  // find left child
		int sid;
		// let sid be the index of A[hole]'s larger child
		if (2 * hole + 2 < size){  // find right child
			sid = A[2 * hole + 1] > A[2 * hole + 2] ? 2 * hole + 1 : 2 * hole + 2;
		}
		else{
			sid = 2 * hole + 1;
		}
		// find the correct hole, stop the loot
		if (x >= A[sid]){
			break;
		}
		A[hole] = A[sid];  // change the location of the nodes
		hole = sid;
	}
	A[hole] = x;  // assign the correct location to x
	return max;
}

4. deleteMin

int deleteMin(int *A, int size){
	if (size == 0){  // the heap is empty
		return -1;
	}
	
	int min = A[0];
	int hole = 0;
	int x= A[--size];

	// percolate down
	while (2 * hole + 1 < size){  // find left child
		int sid;
		// let sid be the index of A[hole]'s larger child
		if (2 * hole + 2 < size){  // find right child
			sid = A[2 * hole + 1] < A[2 * hole + 2] ? 2 * hole + 1 : 2 * hole + 2;
		}
		else {
			sid = 2 * hole + 1;
		}
		// find the correct hole, stop the loot
		if (x <= A[sid]){
			break;
		}
		A[hole] = A[sid];  // change the location of the nodes
		hole = sid;
	}
	A[hole] = x;  // assign the correct location to x
	return min;
}

5. 堆排序

降序用小堆,升序用大堆

// 升序
void HeapSort(int *A, int n) {
  for(int i = 0; i < n; i++) {
    InsertMax(A, i, A[i]);
  }
  for (int i = n - 1; i >= 0; i--){
	  A[i] = deleteMax(A, i+1);
  }
}

// 降序
void HeapSort(int *A, int n) {
  for(int i = 0; i < n; i++) {
    InsertMin(A, i, A[i]);
  }
  for (int i = n - 1; i >= 0; i--){
	  A[i] = deleteMin(A, i+1);
  }
}


🚩 时间复杂度分析

  1. 生成二叉堆: O ( n l o g n ) O(nlogn) O(nlogn)
  2. deleteMax / deleteMin: O ( n l o g n ) O(nlogn) O(nlogn)
  3. 数组复制: O ( n ) O(n) O(n)

The Best Case: O ( n l o g n ) O(nlogn) O(nlogn)
The Worst Case: O ( n l o g n ) O(nlogn) O(nlogn)
The Average Case: O ( n l o g n ) O(nlogn) O(nlogn)




📖 以上均为个人学习数据结构算法时的小笔记,如有错误请多多指正
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值