伪代码的实现:
思路:
将要排序的数拆分成单个数字(单个数字视为有序的),然后比较两个的大小,来排序成正序,之后形成若干个两个数字组成的集合。在这些集合里面,任取两个集合A,B。
其中a1<a2 , b1<b2
于是我们先比较a1和b1,将两个数中较小的数放在第一位(不妨假设a1放了新的排序,记为c1),然后我们再比较a2和b1的大小,若b1较小,则放在新排序的第二位(c2),再比较b2与a2.较小的数字可以再次放在第三位c3(不妨设为b2),最大的数字a2于是放在末尾
举个例子:
A = { 1 , 6 }
B = { 2 ,5 }
于是C第一次先放进1
C = { 1 }
第二次放入 2
C = { 1 , 2 }
第三次放入5
C = { 1 , 2 , 5 }
最后放入 6
C = { 1 ,2 ,5 ,6 }
于是又可以获得一个有序的集合
利用分治思想,我们可以把n个需要排列的数字进行二分,所需要的操作的时间复杂度变为
O
(
n
×
l
o
g
n
)
O(n×logn)
O(n×logn)
> MERGE(A,p,q,r)
> n1 = q - p + 1
> n2 = r - q
> let L[1 … n1 + 1] and R[1…… n2 + 1] be new array
> for i in (1 , n1]
> L[i] = A [p + i - 1]
> for j in (1 , n2]
> R[j] = A[q + j]
> L[n1 + 1] = ∞
> R[n2 + 1] = ∞
> i = 1
> j = 1
> for k in (p,r]
> if L[i] <= R[j]
> A[k] = L[i]
> i++
> else
> A[k] = R[j]
> j++
C语言代码的实现(递归)
#include<stdio.h>
int arr[] = {9,5,3,4,8,1,2,3,4,56};
void merge(int *p1, int p1_size, int *p2, int p2_size)
{
int temp[1000];
int X, i, j;
i = j = X = 0;
while(*(p1 + i) && *(p1 + j) && i < p1_size && j < p2_size)
{
if(p1[i] <= p2[j])
{
temp[X++] = p1[i++];
}
else
{
temp[X++] = p2[j++];
}
}
while(p1[i] && i < p1_size)
{
temp[X++] = p1[i++];
}
while(p2[j] && j < p2_size)
{
temp[X++] = p2[j++];
}
int k;
for(k = 0; k < X; k++)
{
p1[k] = temp[k];//将排序好的内容放回数组中
}
}
void divide_sort(int *p,int size)
{
if(size > 1)
{
int *p1 = p;
int size1 = size / 2;
int *p2 = p1 + size1;
int size2 = size - size1;
divide_sort(p1,size1);
divide_sort(p2,size2);
merge(p1,size1,p2,size2);
}
}
int main()
{ int k = sizeof(arr)/sizeof(arr[0]);
divide_sort(arr,k);
int i;
for(i = 0; i < k; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
Python代码的实现(递归)
def merge(l1, l2):
len1 = len(l1)
len2 = len(l2)
i = j = 0
L = []
while(i < len1 and j < len2):
if(l1[i] < l2[j]):
L.append(l1[i])
i += 1
else:
L.append(l2[j])
j += 1
while i < len1 :
L.append(l1[i])
i += 1
while j < len2 :
L.append(l2[j])
j += 1
return L
def divide(L):
if len(L) < 2:
return L
L1 = divide(L[:len(L)//2])
L2 = divide(L[len(L)//2:])
L3 = merge(L1,L2)
return L3
def main():
L = [5,6,7,3,1,5,7,0,2]
L = divide(L)
print(L)
if __name__ == '__main__':
main()
C语言代码的实现(迭代)
#include<stdio.h>
#include<stdlib.h>
int arr[] = {1,2,9,6,7,4,6,9};
void merge_sort(int p[], int len)
{
int *parr = (int *)malloc( len * sizeof(int) );
int i , j, k, L_min, L_max, R_min, R_max;
for(i = 1; i < len; i*=2)//步长
{
j = 0;
L_min = 0;
/*
三层循环实现
第一层,把数组分成若干个大小规模相当的集合
第二层,跳跃 2*i的位置,进入下一个要排序的数组
第三层,合并 2个i 大小的数组
*/
for( ; j < len ; L_min += i )//这里注意一下,因为L_min后面会变成初始的R_min 所以只需要加一个i的跨度即可
{
L_max = R_min = L_min + i;
R_max = R_min + i;
if(R_max > len)
{R_max = len + 1;}//避免数组越界
for( ;L_min < L_max && R_min < R_max && j < len; )
{
if(p[L_min] < p[R_min])//进行比较
{
parr[j++] = p[L_min++];
}
else
{
parr[j++] = p[R_min++];
}
//printf("%d %d 开始\n",p[j-1],i);
//方便中途输出进行查错
}
while(L_min < L_max && j < len)//把剩余部分放入到临时列表中
{
parr[j++] = p[L_min++];
//printf("%d %d 合并\n",p[j-1],i);
}
while(R_min < R_max && j < len)
{
parr[j++] = p[R_min++];
//printf("%d %d 合并\n",p[j-1],i);
}//排序好规定的两个子列表
}
for(k = 0; k < j ; k++)
{p[k] = parr[k];}
//printf("%d %d \n",parr[k],i);}
}
}
int main()
{
int k = sizeof(arr)/sizeof(arr[0]);
merge_sort(arr, k);
int i = 0;
for(;i < k; i++)
{printf("%d ",arr[i]);}
}