转自http://blog.youkuaiyun.com/zhongkeli/article/details/8786694
下面举例说明一种原地归并排序的思想。
在了解原地归并的思想之前,先回忆一下一般的归并算法,先是将有序子序列分别放入临时数组,然后设置两个指针依次从两个子序列的开始寻找最小元素放入归并数组中;那么原地归并的思想亦是如此,就是归并时要保证指针之前的数字始终是两个子序列中最小的那些元素。文字叙述多了无用,见示例图解,一看就明白。
假设我们现在有两个有序子序列如图a,进行原地合并的图解示例如图b开始
如图b,首先第一个子序列的值与第二个子序列的第一个值20比较,如果序列一的值小于20,则指针i向后移,直到找到比20大的值,即指针i移动到30;经过b,我们知道指针i之前的值一定是两个子序列中最小的块。
如图c,先用一个临时指针记录j的位置,然后用第二个子序列的值与序列一i所指的值30比较,如果序列二的值小于30,则j后移,直到找到比30大的值,即j移动到55的下标;
如图d,经过图c的过程,我们知道数组块 [index, j) 中的值一定是全部都小于指针i所指的值30,即数组块 [index, j) 中的值全部小于数组块 [i, index) 中的值,为了满足原地归并的原则:始终保证指针i之前的元素为两个序列中最小的那些元素,即i之前为已经归并好的元素。我们交换这两块数组的内存块,交换后i移动相应的步数,这个“步数”实际就是该步归并好的数值个数,即数组块[index, j)的个数。从而得到图e如下:
重复上述的过程,如图f,相当于图b的过程,直到最后,这就是原地归并的一种实现思想
上面是http://blog.163.com/zhaohai_1988/blog/static/2095100852012721113044469/分享的,非常感谢
利用上一篇的交换程序可得
- #include <iostream>
- using namespace std;
- template <typename T>
- void swap(T a[],int first,int second){
- T temp;
- temp = a[first];
- a[first] = a[second];
- a[second] = temp;
- }
- template <typename T>
- void reverse(T a[],int begin,int end){
- while(begin < end){
- swap(a,begin++,end--);
- }
- }
- template <typename T>
- void exchange(T a[],int begin,int mid,int end){
- reverse(a,begin,mid);
- reverse(a,mid+1,end);
- reverse(a,begin,end);
- }
- template <typename T>
- void merge(T a[],int begin,int mid,int end){
- int i = begin;
- int j = mid + 1;
- while( i < j && j <= end){
- while(i < j && a[i] <= a[j]){
- i++;
- }
- int old_j = j;
- while(j <= end && a[j] < a[i]){
- j++;
- }
- exchange(a,i,old_j-1,j-1);
- i += (j - old_j);
- }
- }
- template <typename T>
- void merge_sort(T a[],int begin,int end){
- if(begin < end){
- int mid = begin + (end - begin)/2;
- merge_sort(a,begin,mid);
- merge_sort(a,mid+1,end);
- merge(a,begin,mid,end);
- }
- }
- int main() {
- int a[] = {2,3,1,55,6,4,7,3};
- int len = sizeof(a)/sizeof(int);
- int mid = 3;
- merge_sort(a, 0, len-1);
- int i;
- for (i = 0; i < len; ++i)
- cout << a[i] << " ";
- cout << endl;
- }
#include <iostream>
using namespace std;
template <typename T>
void swap(T a[],int first,int second){
T temp;
temp = a[first];
a[first] = a[second];
a[second] = temp;
}
template <typename T>
void reverse(T a[],int begin,int end){
while(begin < end){
swap(a,begin++,end--);
}
}
template <typename T>
void exchange(T a[],int begin,int mid,int end){
reverse(a,begin,mid);
reverse(a,mid+1,end);
reverse(a,begin,end);
}
template <typename T>
void merge(T a[],int begin,int mid,int end){
int i = begin;
int j = mid + 1;
while( i < j && j <= end){
while(i < j && a[i] <= a[j]){
i++;
}
int old_j = j;
while(j <= end && a[j] < a[i]){
j++;
}
exchange(a,i,old_j-1,j-1);
i += (j - old_j);
}
}
template <typename T>
void merge_sort(T a[],int begin,int end){
if(begin < end){
int mid = begin + (end - begin)/2;
merge_sort(a,begin,mid);
merge_sort(a,mid+1,end);
merge(a,begin,mid,end);
}
}
int main() {
int a[] = {2,3,1,55,6,4,7,3};
int len = sizeof(a)/sizeof(int);
int mid = 3;
merge_sort(a, 0, len-1);
int i;
for (i = 0; i < len; ++i)
cout << a[i] << " ";
cout << endl;
}
上面应该算是自顶向下的归并算法,自底向上的归并算法:
- #include <iostream>
- using namespace std;
- template <typename T>
- void swap(T a[],int first,int second){
- T temp;
- temp = a[first];
- a[first] = a[second];
- a[second] = temp;
- }
- template <typename T>
- void reverse(T a[],int begin,int end){
- while(begin < end){
- swap(a,begin++,end--);
- }
- }
- template <typename T>
- void exchange(T a[],int begin,int mid,int end){
- reverse(a,begin,mid);
- reverse(a,mid+1,end);
- reverse(a,begin,end);
- }
- template <typename T>
- void merge(T a[],int begin,int mid,int end){
- int i = begin;
- int j = mid + 1;
- while( i < j && j <= end){
- while(i < j && a[i] <= a[j]){
- i++;
- }
- int old_j = j;
- while(j <= end && a[j] < a[i]){
- j++;
- }
- exchange(a,i,old_j-1,j-1);
- i += (j - old_j);
- }
- }
- template <typename T>
- void merge_sort(T a[],int begin,int end){
- if(begin < end){
- int mid = begin + (end - begin)/2;
- merge_sort(a,begin,mid);
- merge_sort(a,mid+1,end);
- merge(a,begin,mid,end);
- }
- }
- int main() {
- int a[] = {2,3,1,55,6,4,7,3,0};
- int len = sizeof(a)/sizeof(int);
- int step = 1;
- int i = 0;
- for(step = 1;step < len ; step*=2){
- for(i = 0;i+2*step-1 < len; i = i+2*step){
- merge_sort(a, i, i+2*step-1);
- }
- if(i < len){
- merge_sort(a,i,len-1);
- }
- }
- for (i = 0; i < len; ++i)
- cout << a[i] << " ";
- cout << endl;
- }
#include <iostream>
using namespace std;
template <typename T>
void swap(T a[],int first,int second){
T temp;
temp = a[first];
a[first] = a[second];
a[second] = temp;
}
template <typename T>
void reverse(T a[],int begin,int end){
while(begin < end){
swap(a,begin++,end--);
}
}
template <typename T>
void exchange(T a[],int begin,int mid,int end){
reverse(a,begin,mid);
reverse(a,mid+1,end);
reverse(a,begin,end);
}
template <typename T>
void merge(T a[],int begin,int mid,int end){
int i = begin;
int j = mid + 1;
while( i < j && j <= end){
while(i < j && a[i] <= a[j]){
i++;
}
int old_j = j;
while(j <= end && a[j] < a[i]){
j++;
}
exchange(a,i,old_j-1,j-1);
i += (j - old_j);
}
}
template <typename T>
void merge_sort(T a[],int begin,int end){
if(begin < end){
int mid = begin + (end - begin)/2;
merge_sort(a,begin,mid);
merge_sort(a,mid+1,end);
merge(a,begin,mid,end);
}
}
int main() {
int a[] = {2,3,1,55,6,4,7,3,0};
int len = sizeof(a)/sizeof(int);
int step = 1;
int i = 0;
for(step = 1;step < len ; step*=2){
for(i = 0;i+2*step-1 < len; i = i+2*step){
merge_sort(a, i, i+2*step-1);
}
if(i < len){
merge_sort(a,i,len-1);
}
}
for (i = 0; i < len; ++i)
cout << a[i] << " ";
cout << endl;
}
参考: http://zju3053027087.blog.163.com/blog/static/13064377720124732052698/
http://www.cnblogs.com/daniagger/archive/2012/07/25/2608373.html
http://blog.youkuaiyun.com/zheda3072211120/article/details/6427532
http://blog.163.com/zhaohai_1988/blog/static/2095100852012721113044469/
http://www.seenthewind.cn/?p=1105
http://blog.youkuaiyun.com/cjf_iceking/article/details/7920153