归并排序 - 数据结构 - 算法


超全经典排序大汇总


算法思想

将两个或多个有序序列合并为一个有序序列

注:
  1. 二叉树的第 h 层最多有 2h-1 个结点,若树高为 h ,则应该满足 n <= 2h-1 , 即 h − 1 = ⌈ l o g 2 n ⌉ h - 1 = \lceil log{_2}n\rceil h1=log2n, 即趟数 = ⌈ l o g 2 n ⌉ \lceil log{_2}n\rceil log2n
  2. 每趟归并时间复杂度为 O ( n ) O(n) O(n) ,则算法时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
  3. 空间复杂度为 O ( n ) O(n) O(n) ,来自于辅助数组

时间复杂度

  1. 最好 — O ( n l o g n ) O(nlogn) Onlogn
  2. 最坏 — O ( n l o g n ) O(nlogn) O(nlogn)
  3. 平均 — O ( n l o g n ) O(nlogn) Onlogn
注:
归并排序分割子序列与初始序列无关,因此它的最好、最坏、平均时间复杂度均为 O ( n l o g n ) O(nlogn) Onlogn

演示动画

归并.gif

空间复杂度

需要一个辅助数组 ---- O ( n ) O(n) On

稳定性

稳定

适用性

  1. 顺序表
  2. 链表

算法特点

  1. 稳定排序
  2. 可用于顺序结构,也可用于链式结构。使用链式结构不需要附加的存储空间,但递归实现时仍需要开辟相应的递归工作栈。
  3. 一般而言,对于 n n n 个元素进行 k k k 路归并排序时,排序的趟数 m m m 满足 k m = n k^m = n km=n, 从而 m = l o g k n m = log{_k}n m=logkn ,又考虑到 m m m为整数,所以 m = ⌈ l o g k n ⌉ m = \lceil log{_k}n\rceil m=logkn

核心代码

//a[low ... mid] 和 a[mid + 1 ...high]各自有序,将二者归并 
void Merge(int a[], int low, int mid, int high){
	int k = low;
	int i = low, j = mid + 1;//左、右部分首元素 
	
	//将 a数组数据复制到 b数组 
	for(int i = low; i <= high; i ++) b[i] = a[i];
	
	//将 a[low ... mid] 和 a[mid + 1 ...high]归并
	while(i <= mid && j <= high){ 
		if(b[i] < b[j]) a[k ++] = b[i ++];
		else a[k ++] = b[j ++];
	}
	
	while(i <= mid) a[k ++] = b[i ++];//a数组已经枚举完 
	while(j <= high) a[k ++] = b[j ++];//b数组已经枚举完
}  
// 归并排序 
void MergeSort(int a[], int low, int high){//a[low ...high]
	if(low < high){
		int mid = low + high >> 1;//从中间划分 
		MergeSort(a, low, mid);//对左半部分进行归并排序 
		MergeSort(a, mid + 1, high);//对左半部分进行归并排序 
		Merge(a, low, mid, high);//归并 
	}
}

完整代码

#include <iostream> 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>

using namespace std;
const int N = 20;

int num;
int data[N],idx, b[N];

//a[low ... mid] 和 a[mid + 1 ...high]各自有序,将二者归并 
void Merge(int a[], int low, int mid, int high){
	int k = low;
	int i = low, j = mid + 1;//左、右部分首元素 
	
	//将 a数组数据复制到 b数组 
	for(int i = low; i <= high; i ++) b[i] = a[i];
	
	//将 a[low ... mid] 和 a[mid + 1 ...high]归并
	while(i <= mid && j <= high){ 
		if(b[i] < b[j]) a[k ++] = b[i ++];
		else a[k ++] = b[j ++];
	}
	
	while(i <= mid) a[k ++] = b[i ++];//a数组已经枚举完 
	while(j <= high) a[k ++] = b[j ++];//b数组已经枚举完
}  

// 归并排序 
void MergeSort(int a[], int low, int high){//a[low ...high]
	if(low < high){
		int mid = low + high >> 1;//从中间划分 
		MergeSort(a, low, mid);//对左半部分进行归并排序 
		MergeSort(a, mid + 1, high);//对左半部分进行归并排序 
		Merge(a, low, mid, high);//归并 
	}
}

int main(){
	//打开文件 
	ifstream infile;
	infile.open("D:\\学习\\数据结构\\第8章排序\\in.txt", ios::in);
	
	//写文件 
	ofstream outfile;
	outfile.open("D:\\学习\\数据结构\\第8章排序\\out.txt", ios::out);
	
	if(!infile.is_open()){//判断文件打开是否成功 
		cout << "file open failure!" << endl;
	}
	
	infile >> num;//读取元素个数 
	while(num --){//将文件中的元素复制到data[1...n] 数组中
		infile >> data[idx ++];
	}
	
	cout << "排序前元素序列:" << endl;
	for(int i = 0; i < idx; i ++) cout << data[i] << ' '; cout << endl;
	
	cout << "使用sort函数排序后序列: " << endl;
	sort(data, data + idx ); //sort排序区间左闭右开 
	for(int i = 0; i < idx; i ++) cout << data[i] << ' '; cout << endl;
	
	MergeSort(data, 0, idx - 1);
	cout << "使用堆排序后序列为:" << endl;
	for(int i = 0; i < idx; i ++) cout << data[i] << ' '; cout << endl;
	
	num = idx, idx = 0, outfile << num << endl;//写入数据数num以及在行末写入\n 
	while(num --){
		outfile << data[++ idx] << ' ';//将排序后的数据写到文件中 
	}
	outfile << endl;//向文件末尾写入\n结束符 
	
	//关闭文件 
	infile.close();
	outfile.close();
	return 0;
}

输入数据(in.txt)

10
13 69 86 99 59 23 64 32 86 72

输出数据(out.txt)

10
13 23 32 59 64 69 72 86 86 99 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
排序是计算机科学中常见的操作,它将一组元素按照特定的顺序重新排列。排序算法的目标通常是将元素按照升序或降序排列。 常见的排序算法有很多种,每种算法都有不同的时间复杂度和空间复杂度。以下是几种常见的排序算法: 1. 冒泡排序(Bubble Sort):比较相邻的两个元素,如果顺序不正确就交换位置,每次遍历将一个最大(最小)的元素移到最后(最前)。时间复杂度为O(n^2)。 2. 插入排序(Insertion Sort):将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,插入已排序部分的适当位置。时间复杂度为O(n^2)。 3. 选择排序(Selection Sort):每次从未排序部分选择一个最小(最大)的元素放到已排序部分的末尾。时间复杂度为O(n^2)。 4. 快速排序(Quick Sort):选取一个基准元素,将数组划分为两个子数组,小于基准元素的放在左边,大于基准元素的放在右边,然后对子数组进行递归排序。时间复杂度平均情况下为O(nlogn),最坏情况下为O(n^2)。 5. 归并排序(Merge Sort):将数组递归分成两个子数组,然后对子数组进行排序,最后将两个已排序的子数组合并成一个有序数组。时间复杂度为O(nlogn)。 6. 堆排序(Heap Sort):将数组构建成一个最大(最小)堆,每次从堆顶取出最大(最小)元素放到已排序部分的末尾,然后调整堆使其满足堆的性质。时间复杂度为O(nlogn)。 这里只介绍了几种常见的排序算法,每种算法都有其适用的场景和优缺点。在实际应用中,根据数据规模和性能要求选择合适的排序算法非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

soyisou

您的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值