归并法。是将两个,或两个以上的有序表合并为一个新的有序表。两个有序表合并为一个有序表,称为2路归并。排序算法中的归并排序算法,就是把一个需要排序的数组或集合,从中间拆分为2部分,将拆分的两部分,继续拆分,整个拆分过程也是一个递归,直到分解的各个部分为一个元素,一个元素我们也可以称为 只包含一个元素的有序表。
然后,在进行归并操作,一个大的集合或数组,经过上面拆分步骤,已经分为很多小的有序表,整体结构类视一个二叉树结构。从分解出来的最小有序表进行2路归并,合成为一个新的有序表。在归并同时,进行两个有序表的排序。然后,一直归并到整个大的有序表。
c语言实现归并:
/*
** name:sort
author:suju
date:2012-9-11
归并排序法。
method:
void merge(int* num,int start,int mid,int end); //归并方法
void sort(int* num,int start,int end); //数组递归拆分 子有序数组。
*/
#include <stdio.h>
#include <stdlib.h>
/*方法声明*/
void merge(int* num,int start,int mid,int end);
void sort(int* num,int start,int end);
/*main测试函数*/
int main()
{
int num[]={1,34,55,33,33,55,22,4,66,22,44,66,211,33,79,876,4543,3,89};
sort(num,0,19);
int i;
for(i=0;i<19;++i)
{
printf("%d%c",num[i],',');
}
return 0;
}
/*----------------------------------*/
void sort(int* num,int start,int end)
{
int mid=(start+end)/2; /*定义中间拆分变量*/
if (end<=start)
{
return ; /*当递归循环到,子有序数组为1时,return*/
}else
{
sort(num,start,mid); /*从中间拆分右边数组 并递归进行中间继续分解*/
sort(num,mid+1,end); /*拆分左边数组 */
merge(num,start,mid,end); /*归并函数*/
}
}
/*归并函数*/
void merge(int* num,int start,int mid,int end)
{
int* temp=(int*)calloc(end+1,sizeof(int)); /*声明一个临时数组*/
int i,k,j;
/*声明变量,i左边数组起始索引,j左边数组其实索引,j=mid+1.因为mid索引默认分配给左边。k循环变量*/
i=start;k=0;j=mid+1;
while (i<=mid && j<=end) /*当满足数组索引不越界时,进行循环赋值*/
{
if (num[i]>num[j]){
temp[k++]=num[j++]; /*判断左右数组索引对应值,偏小数存数临时数组*/
}else{
temp[k++]=num[i++];
}
}
/*i,j对应数组,上述判断条件,2者肯定有没有遍历完的数组,因为是有序数组,直接遍历在temp后面*/
while (i<=mid) { temp[k++]=num[i++];}
while (j<=end) { temp[k++]=num[j++];}
/*把temp数组赋值给num,num索引位置为start*/
for(i=0;i<k;++i){
num[start+i]=temp[i];
}
free(temp); /*清楚temp*/
}
java语言实现归并,基本操纵都类似。
public class Sort {
public static void main(String[] args) {
/*EXAMPLE*/
int[] num={1,34,55,33,33,55,22,4,66,22,44,66,211,33,79,876,4543,3};
int[] num2={1,34,55,33,33,55,22,4,66,22,44,66,211,33,79,876,4543,3};
sort(num,0,num.length-1);
}
/*数组左右分解操作*/
public static void sort(int[] num,int start,int end)
{
int mid=(start+end)/2; /*获取数组中间变量*/
if (end<=start)
{
return; /*结束索引等于起始索引时,返回*/
}else{
sort(num,start,mid); /*数组右边,并进行递归遍历,直到为一个元素*/
sort(num,mid+1,end); /*数组左边*/
merge(num,start,mid,end); /*归并操作*/
}
}
/*归并操作*/
public static void merge(int[] num,int start,int mid,int end)
{
int[] result=new int[end+1]; /*声明临时数组*/
/*初始化操作变量,i为左边起始索引,j为右边起始索引 k为循环变量*/
int i,j,k;
i=start;
k=0;
j=mid+1; /*初始化变量*/
while(i<=mid && j<=end)
{
if (num[i]>num[j]){ /*当索引不越界时候,进行判断赋值操作*/
result[k++]=num[j++];
}else{
result[k++]=num[i++];
}
}
/*上述循环,i j所表示的数组肯定有一个没有遍历完,因为都是有序数组,直接遍历加到临时数组后面*/
while(i<=mid){
result[k++]=num[i++];
}
while(j<=end){
result[k++]=num[j++];
}
/*把临时数组内容赋值给需要归并的数组*/
for(i=0;i<k;i++){
num[start+i]=result[i];
}
}
}