自学笔记之归并排序
2014-11-26 15:51
211 查看
自学笔记之归并排序
归并排序主要利用了分治思想,它的过程如下:
1.分解成子问题:将n个元素分解为两个具有n/2的子问题。
2.递归求解子问题:利用递归排序这两个子问题。
3.归并子问题:归并子问题的解来产生排序好的答案。
归并排序中最终要的一步是将两个子问题的解合并,在这里我们设计一个函数Merge(A,p,q,r),其中A代表待排序的数组,p,q,r分别表示数组的下标,满足p<=q<r.假设A[p,q]和A[q+1,r]分别是已经排序好的数组,调用这个函数能将其组合为一个排序好的数组A[p…r]。
实现的伪代码如下:
![](https://img-blog.csdn.net/20141126155150078?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFvaGFvZGlr/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
实现过程是利用两个数组来存储已经排序好的子数组,然后将这两个数组合并为一个数组并存储在原数组中。下图1-1为图示过程:
![](https://img-blog.csdn.net/20141126155255921?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFvaGFvZGlr/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图1-1 归并过程图示
下面为归并算法的伪代码:
![](https://img-blog.csdn.net/20141126155352062?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFvaGFvZGlr/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
假设数组的起始下标为1,我们就可以调用Merge-sort(A,1,A.length)实现归并排序。
时间复杂度分析:
由于归并排序的过程就是将一个问题分解为两个同等大小的子问题,并将所得的结果组合。这样我们可以得到时间复杂度的关系式如下:
![](https://img-blog.csdn.net/20141126155438179?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFvaGFvZGlr/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
下图利用递归树求解这个表达式:
![](https://img-blog.csdn.net/20141126155524906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFvaGFvZGlr/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
最后可以求出归并排序的时间复杂度为O(nlgn)。
下图为实现的C++代码:
归并排序主要利用了分治思想,它的过程如下:
1.分解成子问题:将n个元素分解为两个具有n/2的子问题。
2.递归求解子问题:利用递归排序这两个子问题。
3.归并子问题:归并子问题的解来产生排序好的答案。
归并排序中最终要的一步是将两个子问题的解合并,在这里我们设计一个函数Merge(A,p,q,r),其中A代表待排序的数组,p,q,r分别表示数组的下标,满足p<=q<r.假设A[p,q]和A[q+1,r]分别是已经排序好的数组,调用这个函数能将其组合为一个排序好的数组A[p…r]。
实现的伪代码如下:
实现过程是利用两个数组来存储已经排序好的子数组,然后将这两个数组合并为一个数组并存储在原数组中。下图1-1为图示过程:
图1-1 归并过程图示
下面为归并算法的伪代码:
假设数组的起始下标为1,我们就可以调用Merge-sort(A,1,A.length)实现归并排序。
时间复杂度分析:
由于归并排序的过程就是将一个问题分解为两个同等大小的子问题,并将所得的结果组合。这样我们可以得到时间复杂度的关系式如下:
下图利用递归树求解这个表达式:
最后可以求出归并排序的时间复杂度为O(nlgn)。
下图为实现的C++代码:
#include<iostream> using namespace std; #define INFTY 2147483647; void mergesort(int *,int,int); void merge(int *,int,int,int); int main() { int A[10]={3,54,75,34,23,54,345,577,4357,4765}; mergesort(A,0,9); for(int i=0;i<10;i++) { cout<<A[i]<<" "; } cin.get(); return 0; } void mergesort(int *arr,int p,int r) { int q; if(p<r) { q=(p+r)/2; mergesort(arr,p,q); mergesort(arr,q+1,r); merge(arr,p,q,r); } } void merge(int *arr,int p,int q,int r) { int *l1=new int [q-p+2]; int *l2=new int [r-q+1]; for(int i=0;i<q-p+1;i++) l1[i]=arr[p+i]; for(int i=0;i<r-q;i++) l2[i]=arr[q+i+1]; l2[r-q]=INFTY; l1[q-p+1]=INFTY; int i=0; int j=0; for(int k=p;k<=r;k++) { if(l1[i]<=l2[j]) { arr[k]=l1[i]; i++; } else { arr[k]=l2[j]; j++; } } delete [] l1; delete [] l2; }
相关文章推荐
- Asp.Net自学笔记...(函数)
- C#之消息队列的简要说明----自学笔记
- SAP BC402 课程中文自学笔记
- SAP BC404 课程中文自学笔记
- SAP BC407 课程中文自学笔记
- JSP自学笔记
- SAP BC405 课程中文自学笔记
- SAP BC400 课程中文自学笔记
- SAP BC405 课程中文自学笔记
- C#之消息队列的简要说明----自学笔记
- Asp.Net自学笔记...(构造函数和构造函数间的调用)
- SAP BC401 课程中文自学笔记
- Html,JavaScript,正则表达式(reg express) 自学笔记
- Asp.Net自学笔记...(运算符)
- C#之消息队列之自学笔记
- Asp.Net自学笔记...(分支结构和逻辑运算符)
- Asp.Net自学笔记...(对象和属性)
- SAP BC401 课程中文自学笔记
- SAP BC407 课程中文自学笔记
- SAP BC410 课程中文自学笔记