Merge sort including non-recursive version

Table of contents

1. Principle of merge sort

 2. Implement merge sorting

2.1 Framework

2.2 Interval problem and post-order traversal

2.3 Merge and copy

2.4 Merge sort code

2.5 Test

3. Non-recursive implementation of merge sort 

3.1 First implementation

3.2 Testing 

3.3 Modification

 3.4 Modify the test


1. Principle of merge sort

Merge sort is an effective sorting algorithm based on merge operations. This algorithm is a very typical application of the divide-and-conquer method. Merge the ordered subsequences to obtain a completely ordered sequence;

That is, each subsequence is first ordered, and then the subsequence segments are ordered.    If two ordered lists are merged into one ordered list, it is called a two-way merge. 

The content of the array can be imagined as a binary tree. The content of the array is divided into left subtree and right subtree through recursion. The separated left subtree and right subtree have their left subtree and right subtree respectively. Continue to split downward until there is no corresponding interval and the interval has only one element (ordered), then recursively return. Then use the merge method to merge the left subtree and the right subtree into an ordered array, and then copy it to the original array, so that the corresponding subtrees will be in order, and then return recursively, and continue to recurse. Until the root left subtree and the root right subtree are sorted, merge and copy, and the entire array will become sorted.

as the picture shows:

 2. Implement merge sorting

Merge sort requires extra space to assist the implementation.    The reason why it is not implemented in the original array is because if you use exchange to sort, the sorted part of the original array may become unordered again, and using the command If the array is moved backwards for corresponding sorting, the time complexity will be greatly increased. Therefore, merge sorting can be understood as a sorting method that exchanges space for time.

Merge sort requires additional space, but it is obviously unreasonable to open space for each recursion, so we use a function to complete the recursive part. Think about it, what parameters should the newly created function have? First, there must be the original array, and secondly, there must be the array we created. And if we want to form the corresponding recursion like a binary tree, we obviously need an interval, and the formation of the interval requires two Numbers are used to assist, so you can pass in two numbers representing intervals, which can be named begin, end (left, right), which makes it easier to understand.

2.1 Framework

2.2 Interval problem and post-order traversal

Post-order traversal is generally implemented like a binary tree. Note: When begin>=end, it means that the interval does not exist or there is only one element (ordered). Because it is post-order traversal, the boundaries of the intervals need to be calculated before they can be used.

2.3 Merge and copy

It can be seen that each recursion will generate two intervals [begin, mid] and [mid+1, end]. Our goal is to merge these two intervals together. This is very simple and can be done by looping. Note: It is not known which of the two intervals completes the cycle first, so the unfinished cycle interval needs to be added back to the auxiliary array outside.

After completing the merge, use memcpy to copy the contents of the auxiliary array back to the original array, and the sorting is complete. Note: We are passing a closed range, so the length of the copy is, end-begin+1

2.4 Merge sort code

void MergeSort(int*arr,int n)
//将数组和数组的元素个数传递过来
{
	int* a = (int*)malloc(sizeof(int)*n);
	//创建辅助数组
	if (a == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(arr,a,0,n-1);
    free(a);
}
void _MergeSort(int*arr,int*a,int begin ,int end)
{
	//检验区间是否有效
	if (begin >= end)
	{
		return;
	}
	//后序遍历
	int mid = (begin + end) / 2;
	//新区间为[begin,mid],[mid+1,end]
	_MergeSort(arr,a,begin,mid);
	_MergeSort(arr,a,mid+1,end);
    //归并
	int begin1 = begin; int end1 = mid;
	int begin2 = mid+1; int end2 = end;
	//两个区间
	int index = begin;
	//新区间第一个元素的下标
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] <= arr[begin2])
		{
			a[index++] = arr[begin1++];
		}
		else
		{
			a[index++] = arr[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		a[index++] = arr[begin1++];
	}
	while (begin2 <= end2)
	{
		a[index++] = arr[begin2++];
	}
	//将归并好的内容拷贝回原数组
	memcpy(arr+begin,a+begin,(end-begin+1)*sizeof(int));
}

2.5 Test

3. Non-recursive implementation of merge sort 

According to our previous sorting, we can see that its essence is similar to pre-sorting, so we can use an integer such as gap to distinguish one element and one element sorting, two elements and two element sorting.... ...

3.1 First implementation

void MergeSortNonR(int* arr, int n)
{
	int* a = (int*)malloc(sizeof(int) * n);
	//创建辅助数组
	int gap = 1;
	//gap=1便是1个元素和1个元素归并
	while (gap < n)
	{
		int i = 0;
		for (i = 0; i < n; i += 2 * gap)
			//i+=2*gap跳过一整个区间
		{
			//两个区间
			int begin1 = i; int end1 = i + gap - 1;
			int begin2 = i + gap; int end2 = i + 2 * gap - 1;
			int index = i;	//新区间第一个元素的下标
			//归并
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (arr[begin1] <= arr[begin2])
				{
					a[index++] = arr[begin1++];
				}
				else
				{
					a[index++] = arr[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				a[index++] = arr[begin1++];
			}
			while (begin2 <= end2)
			{
				a[index++] = arr[begin2++];
			}
			memcpy(arr + i, a + i, sizeof(int) * (2 * gap));
		}
		gap *= 2;
	}
	free(a);
}

3.2 Testing 

A cross-border problem occurred

The program was aborted before printing

 

3.3 Modification

Observation can find that the first interval is [begin1, end1], and the second interval is [begin2, end2], then begin1 will definitely not cross the boundary, but end1 and the later begin2, end2 may cross the boundary. If end1 and begin2 are out of bounds, it means that they have been sorted. If end2 is out of bounds and begin2 is not, it means that there is still data that has not been sorted.

Think about the details again, end1 is out of bounds, begin2 must be out of bounds, and begin2 is out of bounds, end1 is not necessarily out of bounds, so there is no need to consider end1 out of bounds, as long as begin2 is out of bounds, it means that the sorting has been completed and break directly, and only end2 is out of bounds, then end2 is corrected into an array. The maximum subscript is sufficient.

Note: We used the copy function before to copy 2*gap past, which is obviously inappropriate here. The total interval length should be corrected to end2-begin1. This correction should not be placed at the end, because during the merge, begin1 will + + to end1 should not be placed before beginning2 and end2 are judged to be out of bounds, because end2 may be corrected. To sum up, the resulting code is

void MergeSortNonR(int* arr, int n)
{
	int* a = (int*)malloc(sizeof(int) * n);
	//创建辅助数组
	int gap = 1;
	//gap=1便是1个元素和1个元素归并
	while (gap < n)
	{
		int i = 0;
		for (i = 0; i < n; i += 2 * gap)
			//i+=2*gap跳过一整个区间
		{
			//两个区间
			int begin1 = i; int end1 = i + gap - 1;
			int begin2 = i + gap; int end2 = i + 2 * gap - 1;
			if (begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
				end2 = n - 1;//修正区间长度
			int order = end2 - begin1+1;//修正要拷贝的长度
			int index = i;	//新区间第一个元素的下标
			//归并
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (arr[begin1] <= arr[begin2])
				{
					a[index++] = arr[begin1++];
				}
				else
				{
					a[index++] = arr[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				a[index++] = arr[begin1++];
			}
			while (begin2 <= end2)
			{
				a[index++] = arr[begin2++];
			}
			/*int order = 2 * gap;
			if (2 * gap >= n)
			{
				order = n;
			}*/
			memcpy(arr + i, a + i, sizeof(int) * order);
		}
		gap *= 2;
	}
	free(a);
}

 3.4 Modify the test

At this point, the explanation of the recursive and non-recursive versions of merge sort is completed. Thank you all for visiting me. I wish you all a bright future O(∩_∩)O 

Guess you like

Origin blog.csdn.net/fq157856469/article/details/133546936