归并排序是让我搞了一天才搞明白的一个排序算法(属是笨蛋),其中原理并不复杂,只是把它的原理去归结为代码时,让人十分的头疼。
归并原理:首先一个数组为例,给你一个无序数组,你需要从小到大进行排序
一步一步来,首先把这个数组从中间拆成两段,那么就会产生两个新的数组了对不对(那么有新的数组我们就需要在程序里面创建一个新的数组来接收它),但是他还是一个数组,我们还需要继续拆它,最后就拆成单个的数组,然后再开始合并,一层一层进行合并。
在拆成左右两部分时,在合并的时候先是左边第一个和右边第一个先比较大小,小的插入,当有一边全插入了的时候,把另一边没插完的继续插完为止。
在最后把temp的数组还给arr时要注意它arr[left+i]开始的,而不是直接从零开始的。原因在于插入时不全都是左分支来的,左边可以理解直接从零开始,但是右边却并不是从零坐标开始的,而是本来的中间位置,这时我们用递归把中间的坐标插入时,变成了左边界,所以这个左边界不再是以0开始的,是中间的坐标值,所以我们应该用 arr[left+i]。
void MergeSort(int arr[],int left,int mid,int right) {
int l = left, m_r = mid + 1, k = 0;//m_r 代表着右边支的起点,k代表着我们后面开辟数组需要使用它来插入值
int len = (right - left) + 1; //求出进来的这个数组的长度
int *temp = new int[len];//开辟一个数组来接收传进来的新数组
while (l <= mid&&m_r <= right)//现在开始插入数组,当arr[l]和arr[m_r]都没有到边线时,我们来进行比较谁小谁先插入
temp[k++] = (arr[l] > arr[m_r] ? arr[m_r++] : arr[l++]);
while (l <= mid)//当左边的坐标小于本来中间的坐标时,代表它还有数值可以插入
temp[k++] = arr[l++];
while (m_r <= right)//同上右边的
temp[k++] = arr[m_r++];
for (int i = 0; i < len; i++)//把temp的值赋给arr数组,特别注意:arr[left+i]代表坐标不一定从零开始,可能是从右边的第一个数组坐标开始。
arr[left+ i] = temp[i];
delete[] temp;
}
void split(int arr[], int left, int right) {
if (right > left) { //当右边的最后一个数组坐标大于左边的第一个坐标,就代表还能继续擦拆
int mid = (left + right) / 2; //找出中间值,分成左分治和右分治分别来进行拆分
split(arr, left, mid); //拆左分治
split(arr, mid + 1, right); //拆右分治
MergeSort(arr, left, mid, right);//拆完后形成一个新的数组,需要合并进去
}
}