【归并排序】--递归与非递归实现
程序员文章站
2022-05-10 15:11:43
...
一、2路--归并排序原理:
假设初始序列含有n个元素,则可看成以各个元素为单位是n个有序子序列,每个子序列长度为1,然后两两归并,n个有序子序列就变成了n/2个有序子序列,再两两归并,...,如此重复,直到得到一个长
度为n的有序序列为止。
二、归并排序的两种实现形式:递归实现和非递归实现
三、复杂度
递归实现复杂度:时间复杂度为O(nlogn)空间复杂度为O(n+logn)
四、递归实现代码及测试结果
/**************************************
【2路--归并排序】
Author:tmw
date:2017-11-4
**************************************/
#include <stdio.h>
#include <stdlib.h>
/***递归方法实现归并排序****/
//函数功能:将两个有序表变成一个有序表
//合并
void merge( int array[] , int left , int middle , int right )
{
int left_len = middle - left;
int right_len = right - middle - 1;
int left_array[left_len];
int right_array[right_len];
int i,j,k;
//单独摘出两个有序序列
for( i = 0 ; i <= left_len ; i++ )
left_array[i] = array[i+left];
for( j = 0 ; j <= right_len ; j++)
right_array[j] = array[j+middle+1];
//将两个有序序列变成一个有序序列
//注意:因为后面的排序函数一直是对array数组的递归,因此排序至始至终是对array数组进行,
//array数组元素的位置变化必须体现在array数组里,不能用别的变量代替!!!
k = left;
i = 0;j = 0;
while( i <= left_len && j <= right_len )
{
if( left_array[i] < right_array[j] )
array[k++] = left_array[i++];
else
array[k++] = right_array[j++];
}
while( i <= left_len )
array[k++] = left_array[i++];
while( j <= right_len )
array[k++] = right_array[j++];
}
//merge_sort()先排序,再合并
void merge_sort( int array[] , int left , int right )
{
int middle;
if( left < right )
{
middle = ( left + right ) / 2;
// 分解 + 解决:Divide + Conquer
merge_sort( array , left , middle );
merge_sort( array , middle+1 , right );
// 合并:Combine
merge( array , left , middle , right );
}
}
测试代码及结果
int main()
{
int *array;
int i,array_size;
printf("请输入数组元素的个数:\n");
scanf("%d",&array_size);
array = (int*)malloc(sizeof(int));
printf("请输入 %d 个元素\n",array_size);
for( i = 0 ; i < array_size ; i++ )
scanf("%d",&array[i]);
merge_sort( array , 0 , array_size-1 );
printf("经归并排序后,数组元素顺序输出为:\n");
for( i = 0 ; i < array_size ; i++ )
printf("%d ",array[i]);
return 0;
}
五、非递归实现代码及测试结果
#include <stdio.h>
#include <stdlib.h>
void merge( int array[] , int left , int middle , int right )
{
int left_len = middle - left;
int right_len = right - middle - 1;
int left_array[left_len];
int right_array[right_len];
int i,j,k;
//单独摘出两个有序序列
for( i = 0 ; i <= left_len ; i++ )
left_array[i] = array[i+left];
for( j = 0 ; j <= right_len ; j++)
right_array[j] = array[j+middle+1];
//将两个有序序列变成一个有序序列
//注意:因为后面的排序函数一直是对array数组的递归,因此排序至始至终是对array数组进行,
//array数组元素的位置变化必须体现在array数组里,不能用别的变量代替!!!
k = left;
i = 0;j = 0;
while( i <= left_len && j <= right_len )
{
if( left_array[i] < right_array[j] )
array[k++] = left_array[i++];
else
array[k++] = right_array[j++];
}
while( i <= left_len )
array[k++] = left_array[i++];
while( j <= right_len )
array[k++] = right_array[j++];
}
void merge_sort_interate( int array[] , int array_len )
{
int k;
for( k = 1 ; k < array_len ; k = k*2 )//以2*k作为步进
{
int i = 1;
//int j;
while( i <= array_len-2*k+1 )
{
merge(array,i,i+k-1,i+2*k-1);
i = i+2*k;
}
/**当array_len为奇数情况时,需要考虑最后一个单着的元素**/
if( i < array_len-k+1 )//将最后一个元素与前偶数个归并好的元素最后归并成一个序列
merge(array,i,i+k-1,array_len);
}
}
测试代码及结果:
int main()
{
int *array;
int i,array_size;
printf("请输入数组元素的个数:\n");
scanf("%d",&array_size);
array = (int*)malloc(sizeof(int));
printf("请输入 %d 个元素\n",array_size);
for( i = 1 ; i <= array_size ; i++ )
scanf("%d",&array[i]);
merge_sort_interate( array ,array_size );
printf("经归并排序后,数组元素顺序输出为:\n");
for( i = 1 ; i <= array_size ; i++ )
printf("%d ",array[i]);
return 0;
}
上一篇: 归并排序模板(附求逆序对)
下一篇: 归并排序