栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

排序算法学习笔记

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

排序算法学习笔记

目录
  • 1 快速排序(分治)
    • 1.1 算法流程
    • 1.2 算法代码
  • 2 堆排序(二叉树)
    • 2.1 算法流程
    • 2.2 算法代码

1 快速排序(分治) 1.1 算法流程

假设对长度为 N N N的数组 n u m s nums nums进行升序排序。
(1) 确定第 i i i次排序的范围 [ l i , r i ] [l_i,r_i] [li​,ri​]以及基准点 n u m s [ m i ] nums[m_i] nums[mi​]。其中, l i ≤ m i ≤ r i l_i leq m_i leq r_i li​≤mi​≤ri​随机产生, 0 ≤ l i , r i ≤ N − 1 0 leq l_i, r_i leq N-1 0≤li​,ri​≤N−1。核心思想:在第 i i i次排序中,将比基准点大的值放在其右侧,比基准点小的值放在其左侧。
(2) 将基准点放在右端, s w a p ( n u m s [ m i ] , n u m s [ r i ] ) swap(nums[mi],nums[ri]) swap(nums[mi],nums[ri]),则待排序范围为 [ l i , r i − 1 ] [l_i,r_i-1] [li​,ri​−1]。同时, l i − 1 l_i-1 li​−1表示已经排序,且比基准点小的数值的最右侧的索引。
(3) 令 j j j遍历 [ l i , r i − 1 ] [l_i,r_i-1] [li​,ri​−1],若 n u m s [ j ] < n u m s [ r i ] nums[j] < nums[r_i] nums[j] (4) j j j完成遍历后, s w a p ( n u m s [ l i ] , n u m s [ r i ] ) swap(nums[l_i],nums[r_i]) swap(nums[li​],nums[ri​]),即将基准点放回。此时,基准点左侧的值均小于基准点,右侧的值均大于等于基准点。
(5) 重复步骤(1)~(4),直到对完成对所有元素的排序。

1.2 算法代码
void quickSort(vector& nums, int l, int r) {
	if (l < r) {
		int m = rand() % (r - l + 1) + l;
		swap(nums[m], nums[r]);
		m = l; // 复用变量m,此时记录原始左端索引

		for (int j = l; j < r; ++j) {
			if (nums[j] < nums[r]) {
				swap(nums[j], nums[l]);
				++l;
			}
		}
		
		swap(nums[l], nums[r]);
		quickSort(nums, m, l - 1);
		quickSort(nums, l + 1, r);
	}
}

vector sortArray(vector& nums) {
	int N = nums.size();
	srand(time(0));
	quickSort(nums, 0, N - 1);
	return nums;
}
2 堆排序(二叉树) 2.1 算法流程

堆排序的典型应用场景:每次排序可以获得未排序数组中的最大值(大根堆)或最小值(小根堆),经历过 K ≤ N K leq N K≤N次排序后,即可找到前 K K K个最大值或最小值。
堆排序利用二叉树进行记录数据,其中父节点 i i i的值一定大于子节点 2 i + 1 2i+1 2i+1和 2 i + 2 2i+2 2i+2的值。其中, 0 ≤ i , 2 i + 1 , 2 i + 2 ≤ N − 1 0 leq i,2i+1,2i+2 leq N-1 0≤i,2i+1,2i+2≤N−1。
(1) 自下而上地创建堆。创建的堆满足上述性质。
(2) s w a p ( n u m s [ 0 ] , n u m s [ N − 1 ] ) swap(nums[0],nums[N-1]) swap(nums[0],nums[N−1]),依据堆的性质 n u m s [ 0 ] nums[0] nums[0]为最大值,则按照升序排序的规则,将其交换到数组尾端,并更新数组范围 N = N − 1 N=N-1 N=N−1。
(3) 自上而下地维护堆的性质。由于步骤(2),堆的性质被破坏,需要重新维护堆的性质。

2.2 算法代码
void heapify(vector &arr, int N, int i) {
	int m = i, l = 2 * i + 1, r = 2 * i + 2;
	
	if (l < N && arr[l] > arr[m]) {
		m = l;
	}
	
	if (r < N && arr[r] > arr[m]) {
		m = r;
	}

	if (m != i) {
		swap(arr[m], arr[i]);
		heapify(arr, N, m);
	}
}

void heapSort(vector &arr) {
	int N = arr.size();
	// (1) “自下而上”创建大根堆
	for (int i = N / 2 - 1; i >= 0; --i) {
		heapify(arr, N, i);
	}
	// 排序
	while (N > 1) {
		// (2) 将最大值调换到尾端
		swap(arr[0], arr[--N]);
		// (3) “自上而下”维护大根堆
		heapify(arr, N, 0);
	}

}

int main()
{	
	vector nums = {4, 5, 8, 2, 3, 1, 7, 6};
	// 大根堆实现升序排序
	heapSort(nums);
	for (const int& num : nums) {
		cout << num << endl;
	}
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/698368.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号