算法排序之归并排序算法

归并排序

时间复杂度:O(nlogn)

空间复杂度:O(n)

 

算法思想:

将要排序的数组进行不断切分,切分到最后再逐步进行归并操作。

 

 

 

 

将数组不断切分为2份,层数:log n,如果每层的merge操作都是n,时间复杂度就是O(nlogn)。

归并过程:

开辟一个辅助空间,建立3个索引,一个是当前merge的位置,一个是头一个有序数组操作到的位置,一个是第二个有序数组操作到的位置。

比较两个有序数组第一个位置的两个数,1小,将1放到数组中,第二个有序数组位置+1,

2和4比较,4小,那么2赋值到第二个位置

 

 

实现:

#include <iostream>
#include <algorithm>

using namespace std;

//对arr[l,mid]和arr[mid+1,r]两部分做归并排序 
void merge(int arr[], int l,int mid,int r){
	//辅助空间,存储两部分值
	int tmp[r-l+1];
	for(int i=0; i<r-l+1; i++)
		tmp[i] = arr[l+i];
	
	int i=l,j=mid+1;
	for(int k=l; k<=r; k++)
	{
		if(i>mid) //当i超过mid,第一个数组没有值
		{
			arr[k] = tmp[j-l];
			j++;
		}
		else if(j>r)//当i超过r,第二个数组没有值
		{
			arr[k] = tmp[i-l];
			i++;
		}
		else if(tmp[i-l]<tmp[j-l]) //第一部分值小于第二部分值 
		{
			arr[k] = tmp[i-l];
			i++;
		}
		else //第二部分值小于第一部分值 
		{
			arr[k] = tmp[j-l];
			j++;
		}		
	}
}

//对arr[l,r]之间的数进行归并排序 
void mergeSort(int arr[], int l,int r){
	if(l >= r)
		return;
	int mid = (l+r)/2;
	mergeSort(arr,l,mid);
	mergeSort(arr,mid+1,r);
	merge(arr,l,mid,r); // 归并 
}

 

在两种特殊的情况下:

1.近乎有序的数组进行排序

2.有序的数组进行排序

以上两种情况下,插入排序算法的性能比归并排序算法的性能还要好

 

优化

1.对于数组近乎有序的情况

如果前面有序数组中所有的数都小于后面有序数组中的所有数,说明整个数组是有序的,就不需要进行归并

这点改进后,对于近乎有序的数组

改进前:

改进后:

 

2.当归并排序递归到一定层数的时候,可以转而使用插入排序来提高一些性能。

原因在于:1.当元素数据比较小的时候,数组近乎有序的概率会比较大,此时使用插入排序,就会有优势。2.在时间复杂度前面有一个常数级别,插入排序比归并排序小。当n小于一定程度时,插入排序会比归并排序快一些。

 

自底向上的归并排序算法

思想:

 

两个元素一个小段进行归并

 

四个元素一个小段进行归并

 

8个元素一起归并

 

N=8

sz=1

i=0

Merge(0,1)

 

i=2

Merge(2,3)

 

i=4

Merge(4,5)

 

i=6

Merge(6,7)

sz=2

i=0

Merge(0,1)(2,3)

 

i=4

Merge(4,5)(6,7)

sz=4

i=0

Merge(0,3)(4,7)

 

越界问题:i+size-1可能会越界

 

i+2size-1可能会越界

 

可以使用这个算法对链表进行O(nlogn)的排序

发布了86 篇原创文章 · 获赞 0 · 访问量 4086

猜你喜欢

转载自blog.csdn.net/qq_31965925/article/details/105136339