合并排序(2-路归并排序)算法总结
2016-03-29 20:35
369 查看
合并排序是目前已知稳定的速度最快的排序算法,时间复杂度可以达到O(nlogn),所以很有必要做一次笔记进行总结,而且很多语言中排序方法采用的就是合并排序.
合并排序中心思想是采用两个变量分别标记左右,left和right,在 left到left+size
和 size+1到right之间不断采用分治法,相邻的不断进行比较,不断增加size的大小,最终达到剩余数字数量少于2*size为最终目的,也标志着合并排序的结束。
步骤:
1.首先size为1,每两个比较一次,保证每两个都是顺序的
2.增加size为原来二倍,通过移动指针不停地进行比较排序
3.循环,直到size超过N代表所有的都排序过了
时间复杂度分析:
由于是基本顺序的比较排序,所以每次合并需要O(n)时间。每次需要执行(logn)次合并
所以算法MergeSort需要O(nlogn)的时间
C++代码:
//合并排序
#include "iostream"
#include "cstdlib"
#include "ctime"
#include <windows.h>
using namespace std;
template<class Type>
void MergeSort(Type source[], int n)
{
Type *dest = new Type
;
int size = 1;
while(size < n){
MergePass(source, dest, size, n);//合并到数组dest中,每次排序一次后size增加一次
size += size;
MergePass(dest, source, size, n);//再合并回source中
size += size;
}
}
template<class Type>
void MergePass(Type source[], Type dest[], int size, int n)
{
int left = 0;
while(left <= n - 2 * size){
//合并为大小为s的相邻2段子数组
Merge(source, dest, left, left+size-1, left+2*size-1);
left = left+2*size;
}
//剩下的元素少于2s个
if((left+size) < n)
Merge(source, dest, left, left+size-1, n-1);
else
for(int j = left;j <= n-1; j++)
dest[j] = source[j];
}
template<class Type>
void Merge(Type source[], Type dest[], int left, int mid,int right)
{//两个标志不断移动
int i = left, j = mid+1, k = left;
while((i <= mid) && (j <= right))
if(source[i] <= source[j])
dest[k++] = source[i++];
else
dest[k++] = source[j++];
if(i > mid)
for(int q = j; q <= right; q++)
dest[k++] = source[q];
else
for(int q = i; q<= mid; q++)
dest[k++] = source[q];
}
template<class Type>
void creat(Type source[], int n)
{
srand((unsigned)time(NULL));
for(int i = 0;i < n; i++)
source[i] = rand()%(n*n+50);
}
void main()
{
DWORD TimeStart=GetTickCount();//以毫秒为单位记录时间"windows.h"
int n = 1000;
int *unsort = new int
;
creat(unsort, n);
MergeSort(unsort, n);
for(int i = 0;i < n; i++)
cout<<unsort[i]<<endl;
DWORD TimeEnd=GetTickCount();
TimeEnd -= TimeStart;
cout<<TimeEnd;
}
合并排序中心思想是采用两个变量分别标记左右,left和right,在 left到left+size
和 size+1到right之间不断采用分治法,相邻的不断进行比较,不断增加size的大小,最终达到剩余数字数量少于2*size为最终目的,也标志着合并排序的结束。
步骤:
1.首先size为1,每两个比较一次,保证每两个都是顺序的
2.增加size为原来二倍,通过移动指针不停地进行比较排序
3.循环,直到size超过N代表所有的都排序过了
时间复杂度分析:
由于是基本顺序的比较排序,所以每次合并需要O(n)时间。每次需要执行(logn)次合并
所以算法MergeSort需要O(nlogn)的时间
C++代码:
//合并排序
#include "iostream"
#include "cstdlib"
#include "ctime"
#include <windows.h>
using namespace std;
template<class Type>
void MergeSort(Type source[], int n)
{
Type *dest = new Type
;
int size = 1;
while(size < n){
MergePass(source, dest, size, n);//合并到数组dest中,每次排序一次后size增加一次
size += size;
MergePass(dest, source, size, n);//再合并回source中
size += size;
}
}
template<class Type>
void MergePass(Type source[], Type dest[], int size, int n)
{
int left = 0;
while(left <= n - 2 * size){
//合并为大小为s的相邻2段子数组
Merge(source, dest, left, left+size-1, left+2*size-1);
left = left+2*size;
}
//剩下的元素少于2s个
if((left+size) < n)
Merge(source, dest, left, left+size-1, n-1);
else
for(int j = left;j <= n-1; j++)
dest[j] = source[j];
}
template<class Type>
void Merge(Type source[], Type dest[], int left, int mid,int right)
{//两个标志不断移动
int i = left, j = mid+1, k = left;
while((i <= mid) && (j <= right))
if(source[i] <= source[j])
dest[k++] = source[i++];
else
dest[k++] = source[j++];
if(i > mid)
for(int q = j; q <= right; q++)
dest[k++] = source[q];
else
for(int q = i; q<= mid; q++)
dest[k++] = source[q];
}
template<class Type>
void creat(Type source[], int n)
{
srand((unsigned)time(NULL));
for(int i = 0;i < n; i++)
source[i] = rand()%(n*n+50);
}
void main()
{
DWORD TimeStart=GetTickCount();//以毫秒为单位记录时间"windows.h"
int n = 1000;
int *unsort = new int
;
creat(unsort, n);
MergeSort(unsort, n);
for(int i = 0;i < n; i++)
cout<<unsort[i]<<endl;
DWORD TimeEnd=GetTickCount();
TimeEnd -= TimeStart;
cout<<TimeEnd;
}
相关文章推荐
- Eclispe中web.xml无自动提示问题
- javacv1.1环境配置
- UVA 11090 Going in Cycle!!
- Spring概述
- Java守护线程
- C++实验二:正整数
- Hello--Spring
- Go语言学习二 :常数和条件语句
- PHP&MySQL(三)——数组
- 作业4.2
- PHP 基本用法及基本知识点
- duplicate symbol _OBJC_IVAR_$
- 求n的阶乘
- 【剑指 offer】—— 快速排序
- struts2实现让文件输入流流向浏览器显示
- 第5周项目1—三角形类雏形(2、内联成员函数)
- js学习
- 设置一个三角形类(3)
- nyoj 1045 看美女(二)
- 好的资源