归并和快排用到的都是分治的思想,关于归并排序的步骤可以看我之前的文章,里边有动图和文字描述,很容易理解,关于快排的代码实现在之前已经写过,今天我们来看一下归并排序的代码实现。
归并排序思想是将待排序的序列递归地分为左右两个子序列,直到子序列无法在分割,即只剩下一个元素的时候,将划分好的子序列按大小顺序合并,最后得到的序列就是有序的。
在进行归并的时候,我们使用两个指针i,j分别指向左边序列[l,mid],和右边序列[mid+1,r]的第一个元素的位置,再创建临时数组tem,用指针k指向tem的首位,之后,分别比较左右两个序列,将小的放到临时数组tem中,并将小的那个序列和临时序列都向前移动一个位置。左右两个子序列其中一个指向最后一个元素,则将另一个序列剩下的元素完全放到tem中,最后将tem中的元素放回到原数组的[l,r]位置即可。具体代码如下:
class Solution {
public:
vector<int> tem;
void merge_sort(vector<int>& nums , int l,int r){
if(r<=l) return;
int mid = l + (r-l)/2; //将子列从中间为分界划开
merge_sort(nums,l,mid); //递归的划分左子列
merge_sort(nums,mid+1,r); //递归的划分右子列
int i = l, j = mid +1 , k = 0;
while(i<=mid && j <= r){ //将左右子列中较小的元素放到临时数组中
if(nums[i] <= nums[j]) tem[k++] = nums[i++];
else tem[k++] = nums[j++];
}
//如果右子列已无元素将左子列剩下的元素放到临时数组后边
while(i<=mid) tem[k++] = nums[i++];
//如果左子列已无元素将右子列剩下的元素放到临时数组后边
while(j<=r) tem[k++] = nums[j++];
//将临时数组中的元素放回到原数组的[l,r]位置
for(int i = 0;i<= r-l;i++){
nums[i+l] = tem[i];
}
}
vector<int> sortArray(vector<int>& nums) {
tem.resize(nums.size());
merge_sort(nums,0,nums.size()-1);
return nums;
}
};