Merge sort (detailed code implementation)

Many online merging and sorting articles focus on the principle of merging and sorting, but they don't pay much attention to the code implementation, so let's take a look at the code implementation of merging algorithm in this chapter.

principle

To learn an algorithm, you must first learn its principle~

Merge sort, using the idea of divide and conquer, first divide the array into half groups until there is only one element in each group, then sort and merge the array, and finally turn it into a completely ordered array.

In the last animation demonstration, the dynamic diagram of the up main of "five minute learning algorithm" is quoted here. I think it's good

Although the animation demonstration is grouped at the same time, when you debug the code, you will find that it is divided into one side first and then the other side

There is also a picture that I think is quite good, which well reflects the idea of divide and conquer.

code implementation

Let's first look at the implementation of the merge section

void merge(int low,int mid,int high)
{
	int left = low;	//Array pointer in the left part
	int right = mid + 1;	//Right part pointer
	int k = low;	//Pointer to the temp array

	while (left < mid + 1 && right < high + 1) {  /*This while is used to combine two arrays into a new one			 				
													Array, which is temporarily stored in temp []*/
		if (nums[left] > nums[right]) {
			temp[k++] = nums[right++];	//k + + and right + + here mean to assign values first and then add 1
		}								//It's equivalent to the following else
		else {
			temp[k] = nums[left];
			k++;
			left++;
		}
	}

	//Check whether the left sequence is empty
	while (left < mid + 1) {		/*These two while are used to store the values of one array and leave the other array											
										The elements are stored in sequence*/
		temp[k++] = nums[left++];
	}

	//Check whether the sequence on the right is empty
	while (right < high + 1) {
		temp[k++] = nums[right++];
	}

	//Move back to the original array. num[i] is the array defined in the global area to be sorted
	for (int i = low; i <= high; i++) {	//i=low here. It can't be equal to 0
		nums[i] = temp[i];
	}
}

Code implementation of the mergeSort part

void mergeSort(int low,int high)	//Use recursion
{
	if(low >= high) {	//It is equivalent to a group of single elements. Just return it directly
		return;
	}
	int mid = low + ((high - low) >> 1);/*Prevent low and high from crossing the boundary. 1 is the same as dividing by 2, but	
											Faster than / 1 efficiency*/
	//branch
	mergeSort(low, mid);	//First on the left
	mergeSort(mid + 1, high);	//Finish left and right

	//cure
	merge(low, mid, high);	//Merge layer by layer, and small arrays are gradually merged into large arrays
}

Finally, let's take a look at the complete specific code

#include <iostream>
using namespace std;

int nums[7] = { 7,3,5,2,9,8 };//Array to be sorted
int temp[7];//Temporary storage array

void merge(int low,int mid,int high)
{
	int left = low;	//Array pointer in the left part
	int right = mid + 1;	//Right part pointer
	int k = low;	//Pointer to the temp array

	while (left < mid + 1 && right < high + 1) {
		if (nums[left] > nums[right]) {
			temp[k++] = nums[right++];
		}
		else {
			temp[k] = nums[left];
			k++;
			left++;
		}
	}

	//Check whether the left sequence is empty
	while (left < mid + 1) {
		temp[k++] = nums[left++];
	}

	//Check whether the sequence on the right is empty
	while (right < high + 1) {
		temp[k++] = nums[right++];
	}

	//Move back to the original array
	for (int i = low; i <= high; i++) {	//i=low here. It can't be equal to 0
		nums[i] = temp[i];
	}
}

void mergeSort(int low,int high)
{
	if(low >= high) {
		return;
	}
	int mid = low + ((high - low) >> 1);//To prevent low and high from crossing the boundary, 1 is the same as dividing by 2, but it is faster than / 2
	//branch
	mergeSort(low, mid);
	mergeSort(mid + 1, high);

	//cure
	merge(low, mid, high);
}

int main()
{
	mergeSort(0, 5);
	for (int i = 0; i <=5; i++) {
		cout << nums[i] << " ";
	}
	cout << endl;
	return 0;
}



It is better to debug the code and see the change of variable value, which will make the implementation of merging algorithm more clear.

Complexity analysis

  • Time complexity:

    From this recursive tree, we can see that the time cost of the first layer is cn, the time cost of the second layer is cn/2+cn/2=cn... The cost of each layer is cn, and there are a total of logn+1 layers, so the total time cost is cn*(logn+1). The time complexity is O(nlogn)

  • Space complexity: the merge sort algorithm requires an additional sequence temp [] to store the sorted results. The space occupied is n, so the space complexity is O(n)

  • Stability: in the worst, best and average cases, the time complexity of merging and sorting is O(nlogn). It can be seen from the merging process that the merging and sorting is stable.

Summary:

Merge sort algorithm is efficient, because its time complexity is only O(nlogn), so when there is a large amount of data, merge sort is a good choice. For C friends who don't know much about the divide and conquer idea in the algorithm, you can check the concept first, and then understand the code implementation with the help of debugging.

Tags: Algorithm data structure

Posted on Fri, 15 Oct 2021 22:02:58 -0400 by theCro