选择排序&堆排序

本文探讨了两种常见的排序算法——选择排序和堆排序。选择排序的时间复杂度为O(N^2),通过两个for循环实现。而堆排序作为一种选择排序,其时间复杂度在最好、最坏、平均情况下均为O(nlogn),并且是一种不稳定排序。堆是一个完全二叉树,通过不断取出最大值或最小值来完成排序。最大堆适用于选择排序,而最小堆则需要额外空间,不是最优方式。
摘要由CSDN通过智能技术生成

选择排序(SlectionSort)

相关概念

  • 在使用两个for循环的情况下,选择排序的平均时间复杂度为O(N^2)

实现描述

1、实现思想

template<typename T>
void SelectionSort(vector<T>& vec) {
	for (int i = 0; i < vec.size(); ++i) {
		// 从i到容器末尾找最小元,并返回位置。如果直接使用for循环将使时间复杂度到达O(N^2)
		int minPos = ScanForMin(vec, i);
		// 将未排序的最小元和目前的i进行交换,则i之前的位置都是有序部分
		std::swap(vec[i], vec[minPos]);
	}
}

 2、简单实现

template<typename T>
void SelectionSort(vector<T>& vec) {
	for (int i = 0; i < vec.size(); ++i) {
		int minPos = i;
		for (int j = i; j < vec.size(); j++) {
			minPos = vec[j] < vec[minPos] ? j : minPos;
		}
		std::swap(vec[i], vec[minPos]);
	}
}

堆排序(HeapSort)

参考链接:https://www.cnblogs.com/chengxiao/p/6129630.html

相关概念

  • 堆排序是一种选择排序,它的最好、最坏、平均时间复杂度均为O(nlogn);同时堆排序也是不稳定排序
  • 堆是一个完全二叉树,某一节点的值总是不大于或不小于其它孩子节点的值
  • 堆的每个节点的子树都是堆
  • 以最大堆进行选择排序为例,由于根节点的值是最大的,每次取出最大值,剩余的再建堆,再取出最大值,以此循环(为什么不取剩下左右子节点的值?因为左右节点的值中有一个肯定是最大值,但另一个就不一定是最大值了)
  • 如果使用最小堆进行排序,那么就需要额外的O(N)的空间,并不是最好的方式

实现描述

 

template<typename T>
void AdjustHeap(vector<T>& vec, int i, int length) {
	T tmp = vec[i]; // 先取出当前元素i
	// 从i结点的左子结点开始,也就是2i+1处开始
	for (int k = i * 2 + 1; k < length; k = 2 * k + 1) {
		// 如果左子结点小于右子结点,k指向右子结点
		if (k + 1 < length && vec[k] < vec[k + 1])
			k++;
		if (vec[k] > tmp) { // 如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
			vec[i] = vec[k];
			i = k;
		}
		else
			break;
	}
	vec[i] = tmp; // 将tmp值放到最终的位置
}

template<typename T>
void HeapSort(vector<T>& vec) {
	// 构建最大堆
	for (int i = vec.size() / 2 - 1; i >= 0; i--) {
		AdjustHeap(vec, i, vec.size());
	}
	// 调整堆结构+交换堆顶元素与末尾元素
	for (int j = vec.size() - 1; j > 0; j--) {
		std::swap(vec[0], vec[j]);
		AdjustHeap(vec, 0, j);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值