数据结构算法学习总结-慕课网(八)归并排序(自底向上,从小到大)

数据结构算法学习总结-慕课网(八)归并排序(自底向上,从小到大)

1.回顾

上一节讲到自顶向下递归的归并排序的优化,我们完全可以自底向上归并,不需要使用递归

2.实战

main.cpp

#include 
#include "SortTestHelper.h"
#include "MergeSort.h"
#include "InsertSort.h"

using namespace std;

/**
 * 自底向上的归并
 */
template
void mergeSortBU(T arr[],int n){
	for(int sz =1;sz <= n;sz+=sz){
		for(int i = 0;i + sz < n;i+=sz+sz){
			//优化1,近乎有序的数组进行插入排序
			if(i >= i+sz+sz-1-15){
				insertSort(arr,i,i+sz+sz-1);
			}
			//优化2,类似2 3|4 5这样的左右都是有序的,3比4小,那么整个数组就是从小到大的,不需要排序
			if(arr[i+sz-1] > arr[i+sz-1+1]){
			__merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1));
			}
		}
	}
}

int main(){
	int n = 100000;
	int* arr = SortTestHelper::generateNearlyOrderedArray(n,100);
	int* arr1 = SortTestHelper::copyArray(arr,n);

	SortTestHelper::testSort("Merge Sort BU:",mergeSortBU,arr,n);
	SortTestHelper::testSort("Merge Sort:",mergeSort,arr1,n);
	delete[] arr;
	return 0;
}

MergeSort.h

#ifndef MERGESORT_H_
#define MERGESORT_H_
#include 
#include "InsertSort.h"
/**
 * 将[l...mid]和[mid+1...r]两部分进行归并
 */
template
void __merge(T arr[],int l,int mid,int r){
	//临时空间,存贮arr的数组
	T aux[r-l+1];
	for(int i = l;i<=r;i++)
		aux[i-l]=arr[i];

	int i = l,j=mid+1;
	for(int k = l;k<=r;k++){
		//i>mid表示i所在数组已经归并完,j所在的数组没有归并完,还需要归并一次
		if(i > mid){
			arr[k] = aux[j-l];
			j++;
		}else if(j > r){//j>r表示j所在数组已经归并完,i所在的数组没有归并完,还需要归并一次
			arr[k] = aux[i-l];
			i++;
		}else if(aux[i-l]
void __mergeSort(T arr[],int l,int r){
//	if(l >= r)
//		return;
	//优化2
	if(l >= r-15){
		insertSort(arr,l,r);
		return;
	}
	int mid = (l+r)/2;
	__mergeSort(arr,l,mid);
	__mergeSort(arr,mid+1,r);
	//优化1
	if(arr[mid] > arr[mid+1]){
		__merge(arr,l,mid,r);
	}
}

template
void mergeSort(T arr[],int n){
	__mergeSort(arr,0,n-1);
}
#endif

运行结果

Merge Sort BU: : 0.007s

Merge Sort: : 0.005s

总结

自底向上的归并和自顶向下的归并效率差不多,严格的说自顶向下的效率会更好一些

自底向上的归并有一个优势是,可以实现对链表的排序,有兴趣的同学可以自己研究一下

意见与建议

如果博友有任何问题或者建议,欢迎留言讨论

你可能感兴趣的:(数据结构算法,c++)