归并排序-乡巴老都能看懂
基本思想
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
分而治之
首先我们要知道如何分解?
1.将一串长度为8个元素的数组分成 两个部分 两个部分在分成四个部分 四个部分分成八个部分
方法:
//分解
if(left >= right)
return;
mid = (left + right +1) /2 ;//把大的序列从中间划分为两个小序列
//mid指向右边的第一个元素
//对左边的递归进行分解、
MergerSort(arr,left,mid-1,tmp);
//对右边的递归进行分解
MergerSort(arr,mid,right,tmp);
如何合并?
//合并
void merger (int arr[], int left, int mid,int right , int tmp[])
{
int i = left; //左边的第一个元素
int j = mid ; //右边的第一个元素 。right 是右边的最后一个元素
int index = left ; //辅助数组相对应的起始位置
while(i<mid && j <=right) //如果左面还没有到达中间位置,并且 右面也没有到达最后的位置
{
if (arr[i] < arr[j]) //如果左面第一个值<右面第一个值
{
tmp[index] = arr[i]; //将最小的值放在 临时数组的index的位置;
i++; //依次往后
}
else
{
tmp[index] = arr[j]; //如果J最小就将J放在临时数组的index位置
j++;
}
index++; //如果这一组在一个以上,index++; 确保位置的准确
}
//如果 其中某一边只剩下 最后一个元素 进行处理
while(i<mid) //i<右面的第一个元素
{
tmp[index] = arr[i]; //直接放置
i++;
index++;
}
//判断j有没有越界,没有越界把剩下的所有元素放入辅助数组中
while(j<=right)
{
tmp[index] = arr[j];
j++;
index++;
}
//把辅助数组中的元素放回原数组
for(i = left ; i<=right; i++)
arr[i] = tmp[i];
}
如何排序?
直接看实例
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10
//打印数组
void PrintArray(int arr[], int n)
{
int i ;
for(i= 0 ; i<n;i++)
{
printf("%2d ",arr[i]);
if((i+1) % 20 == 0)
printf("\n");
}
printf("\n--------------------------------\n");
}
//合并
void merger (int arr[], int left, int mid,int right , int tmp[])
{
int i = left; //左边的第一个元素
int j = mid ; //右边的第一个元素 。right 是右边的最后一个元素
int index = left ; //辅助数组相对应的起始位置
while(i<mid && j <=right) //如果左面还没有到达中间位置,并且 右面也没有到达最后的位置
{
if (arr[i] < arr[j]) //如果左面第一个值<右面第一个值
{
tmp[index] = arr[i]; //将最小的值放在 临时数组的index的位置;
i++; //依次往后
}
else
{
tmp[index] = arr[j]; //如果J最小就将J放在临时数组的index位置
j++;
}
index++; //如果这一组在一个以上,index++; 确保位置的准确
}
//如果 其中某一边只剩下 最后一个元素 进行处理
while(i<mid) //i<右面的第一个元素
{
tmp[index] = arr[i]; //直接放置
i++;
index++;
}
//判断j有没有越界,没有越界把剩下的所有元素放入辅助数组中
while(j<=right)
{
tmp[index] = arr[j];
j++;
index++;
}
//把辅助数组中的元素放回原数组
for(i = left ; i<=right; i++)
arr[i] = tmp[i];
}
//归并排序
void MergerSort (int arr[],int left , int right, int tmp[])
{
int mid ;
//分解
if(left >= right)
return;
mid = (left + right +1) /2 ;//把大的序列从中间划分为两个小序列
//mid指向右边的第一个元素
//对左边的递归进行分解、
MergerSort(arr,left,mid-1,tmp);
//对右边的递归进行分解
MergerSort(arr,mid,right,tmp);
//对两个小的有序序列进行合并
merger(arr,left, mid ,right,tmp);
}
int main()
{
int arr[N];//带排序的数组
int tmp[N];//辅助数组
int i;
srand((unsigned int )time(NULL));
for(i=0;i<N;i++)
{
arr[i] = rand()%100 ;
}
PrintArray(arr,N);
MergerSort(arr,0,N-1,tmp);
PrintArray(arr, N);
return 0;
}