【手撕排序3】归并排序

在这里插入图片描述
🍃 本系列包括常见的各种排序算法,如果感兴趣,欢迎订阅🚩
🎊个人主页:小编的个人主页
🎀 🎉欢迎大家点赞👍收藏⭐文章
✌️ 🤞 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 👍

🐼前言

🌟在上一节我们实现了快速排序,感受到了快速排序的魅力,如果感兴趣的小伙伴,可以阅读我的上一篇文章:> 快速排序,这节小编将带领大家感受归并排序的美学。

🐼归并排序

🔍归并排序采用分治的思想,将一组乱序的数字先二分,再二分,直到不能二分,此时每个子序列有序。再使子序列段间有序直到得到一个完全有序的子序列。再将得到的子序列合并成一个有序表。
如图:
在这里插入图片描述
🔍我们先取中间值mid二分,划分左右两个序列([left,mid],[mid+1,right])直到划分为一个元素,那么该元素就是有序的。
🔍在进行合并,将划分的两个有序数组进行合并。
总结来说,递归进行分解,回溯进行合并
归并排序代码:

void _MergeSort(int* arr,int left,int right,int* tmp)
{
	if (left >= right)
	{
		return;
	}
	//二分
	int mid = left + (right - left) / 2;
	//根据Mid划分为两个序列 [left,mid] [mid+1,right]
	_MergeSort(arr, left, mid,tmp);
	_MergeSort(arr, mid + 1, right,tmp);

	//合并两个有序数组[left,mid] [mid+1,right]
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = begin1;//从begin1开始
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] < arr[begin2])
		{
			tmp[index++] = arr[begin1++];
		}
		else
		{
			tmp[index++] = arr[begin2++];
		}
	}
	//[left,mid]还有元素
	while (begin1 <= end1)
	{
		tmp[index++] = arr[begin1++];
	}
	//[mid + 1, right]还有元素
	while (begin2 <= end2)
	{
		tmp[index++] = arr[begin2++];
	}
	//将新数组拷贝到原数组
	for (int i = left; i <= right; i++)
	{
		arr[i] = tmp[i];
	}
}
//归并排序
void MergeSort(int* arr, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSort(arr, 0, n - 1,tmp);
	free(tmp);
	tmp = NULL;
}

🔍为了不在原来的数组上进行合并,我们创建了一个临时数组来保存合并好的有序序列,最后,将新数组拷贝到原数组。
归并排序性能分析:

递归深度为O(logn),合并两个有序序列为O(N),所以,归并排序的时间复杂度为O(n*logn).空间复杂度为O(N);

🍀测试结果:
排序数组:{ 4,6,7,2,1,8,9,5,3 ,0 }在这里插入图片描述

🐼文末

感谢你看到这里,如果觉得本篇文章对你有帮助,点个赞👍 吧,你的点赞就是我更新的最大动力 ⛅️🌈 ☀️

### 冒泡排序算法详解 冒泡排序是一种经典的排序算法,其核心思想是比较相邻的元素并将较大的元素逐步向数组末端移动[^1]。以下是基于 C++ 的具体实现代码: ```cpp #include <iostream> using namespace std; // 定义交换函数 void swap(int& a, int& b) { int temp = a; a = b; b = temp; } // 冒泡排序实现 void bubble_sort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { // 外层循环控制遍历次数 bool swapped = false; // 添加标志位用于优化 for (int j = 0; j < n - 1 - i; j++) { // 内层循环完成单次比较 if (arr[j] > arr[j + 1]) { // 如果前一个元素大于后一个,则交换 swap(arr[j], arr[j + 1]); swapped = true; // 记录本次是否有发生交换 } } if (!swapped) break; // 若某一轮未发生任何交换,则提前结束 } } ``` #### 关键点解析 上述代码实现了标准的冒泡排序逻辑,并引入了一个 `swapped` 标志变量来提升效率[^3]。如果在某一趟遍历中没有任何元素被交换,则说明序列已经有序,可以立即终止后续操作。 --- ### 测试示例 为了验证该算法的有效性,可以通过以下测试用例观察运行效果: ```cpp int main() { int data[] = {64, 34, 25, 12, 22, 11, 90}; int size = sizeof(data) / sizeof(data[0]); cout << "原始数据: "; for (int i = 0; i < size; ++i) { cout << data[i] << " "; } bubble_sort(data, size); cout << "\n排序结果: "; for (int i = 0; i < size; ++i) { cout << data[i] << " "; } return 0; } ``` 执行以上程序会得到如下输出: ``` 原始数据: 64 34 25 12 22 11 90 排序结果: 11 12 22 25 34 64 90 ``` 此过程展示了如何通过多轮比较和交换最终使整个数组按升序排列。 --- ### 性能分析 冒泡排序的时间复杂度为 O(n²),其中最坏情况发生在输入完全逆序时;而最佳情况下(即输入已近似有序),由于加入了优化机制,时间复杂度可降为 O(n)。尽管如此,在实际应用中通常不推荐使用冒泡排序处理大规模数据集,因为存在更高效的替代方案如快速排序归并排序[^2]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值