一.定义
简单的来说就是将原问题分解为规模较小的子问题,几个规模较小的子问题类似于原问题,递归的求解子问题,将子问题合并,建立原问题的解。
二.原理与复杂度
递归树
动图演示:
*在菜鸟教程中得到的动图
T(n)问题逐步分解为递归树,归并同理。总代价为θ(nlgn);
实现一个简单的分治排序先用伪代码表示,这里需要用到两个函数Merge于MergeSort,
Merge(A,p,q,r)
n1 = q-p+1
n2 = r-q
Let L[1...,n1+1] and R[1...,n2+1] to new Arrays
for i=1 to n1
L[i] = A[p+i-1]
for j=1 to n2
R[j] = A[q+j]
L[n1+1] = max
R[n2+1] = max
i=1,j=1
for k=p to r
if L[i] <= R[j]
A[K] = L[i]
i++;
else
A[K] = R[j]
j++
p为第一个元素,q为中间元素,r为末尾元素
将传递的A数组分为两个数组,将两个数组大小设置为Half+1,多出来的为哨兵。进行循环比较大小,将小的元素归并回原数组。
MergeSort(A,p,r)
if p < r
q = [(p+r)/2]
MergeSort(A,p,q)
MergeSort(A,q+1,r)
Merge(A,p,q,r)
MergeSort进行递归,通过数组两个部分的MergeSort分成子问题,再通过Merge进行归并。
三.C++实现
#include<iostream>
using namespace std;
void Merge(int nums[], int begin, int half, int end) {
int n1 = half - begin + 1;
int n2 = end - half;
int* L = new int[n1 + 1];
int* R = new int[n2 + 1];
for (int i = 0; i < n1; i++) {
L[i] = nums[begin + i];
}
for (int j = 0; j < n2; j++) {
R[j] = nums[half + j + 1];
}
L[n1] = 1000;
R[n2] = 1000;
int i = 0, j = 0;
for (int k = begin; k <= end; k++) {
if (L[i] <= R[j]) {
nums[k] = L[i];
i++;
}
else {
nums[k] = R[j];
j++;
}
}
}
void MergeSort(int nums[], int begin, int end) {
if (begin < end) {
int half = (end + begin) / 2;
MergeSort(nums, begin, half);
MergeSort(nums, half + 1, end);
Merge(nums, begin, half, end);
}
}
int main() {
int nums[10];
for (int i = 0; i < 10; i++)
cin >> nums[i];
MergeSort(nums, 0, size(nums) - 1);
for (int i = 0; i < size(nums); i++)
cout << nums[i] << " ";
return 0;
}
MergeSort负责拆分,Merge负责归并,比较简单自己看看就能懂
测试结果
四.Java实现
package Main;
import java.util.Scanner;
public class Test {
public static void main(String[] args){
int[] nums = new int[10];
Scanner input = new Scanner(System.in);
for(int i=0;i<nums.length;i++)
nums[i] = input.nextInt();
MergeSort(nums,0,nums.length-1);
for(int i=0;i<nums.length;i++){
System.out.print(nums[i]+" ");
}
}
public static void MergeSort(int[] nums,int begin,int end){
if(begin<end) {
int half = (end + begin) / 2;
MergeSort(nums, begin, half);
MergeSort(nums, half + 1, end);
Merge(nums, begin, half, end);
}
}
public static void Merge(int[] nums,int begin,int half,int end){
int[] temp = new int[end-begin+1];
int i = begin,j = half+1,k = 0;
while(i <= half && j <= end){ //循环将小的放入temp数组
if(nums[i] <= nums[j])
temp[k++] = nums[i++];
else
temp[k++] = nums[j++];
}
while(i <= half)
temp[k++] = nums[i++]; //将剩余的放入临时数组
while(j <= end)
temp[k++] = nums[j++];
for(int i1 = 0;i1 < temp.length;i1++)
nums[i1 + begin] = temp[i1];
}
}
在java的实现上与C++的实现略有不同,在java中用到了临时数组。
测试:
最后:好久没有写C++了忘了许多(叹……)