Algorithm sort 2 Insert or Merge

All weekly assignments and video thinking questions for answers and analysis see  Zhejiang University Data Structure Thinking Questions + Weekly Practice Answers

Title: According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Merge sort works as follows: Divide the unsorted list into N sublists, each containing 1 element (a list of 1 element is considered sorted). Then repeatedly merge two adjacent sublists to produce new sorted sublists until there is only 1 sublist remaining.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in the first line either "Insertion Sort" or "Merge Sort" to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resuling sequence. It is guaranteed that the answer is unique for each test case. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

translation:

Insert sort iteration, reuse one input element each time, and increase the sorted output list. At each iteration, the insertion sort removes an element from the input data, finds its position in the sorted list, and inserts it. It will repeat until no input elements are retained.

The working principle of merge sort is as follows: the unsorted list is divided into N sub-lists, and each sub-list contains 1 element (a list of 1 elements is regarded as sorted). Then repeatedly merge two adjacent sublists to generate a new sorted sublist until only one sublist remains.

Now given the initial sequence of integers , plus a sequence, this sequence is the result of multiple iterations of a sorting method , can you tell which sorting method we are using?

Input specifications:

Each input file contains a test case. For each case, the first line gives a positive integer N (≤100). In the next line, N integers are used as the initial sequence. The last row contains a partially ordered sequence of N numbers. It is assumed that the target sequence is always increasing. All numbers in a line are separated by spaces.

Output specifications:

For each test case, print "insert sort" or "merge sort" on the first line to indicate the method used to obtain partial results. Then run this method again for an iteration, and output the result sequence on the second line. Ensure that the answer to each test case is unique. All numbers in a line must be separated by spaces, and there must be no extra spaces at the end of the line.

Sample Input 1:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

Sample Output 1:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

Sample Input 2:

10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

Sample Output 2:

Merge Sort
1 2 3 8 4 5 7 9 0 6

answer:

The difficulty lies in how to find which sort it is used for.

First of all, we know that if the end of the second line is out of order and the same as the end of the first line, it should be inserted sort. Because the insertion sort is from front to back, so only a limited number of iterations will not change the order that has not been iterated later. And the first part of the second row of the insertion sort must be already sorted.

That is, the sequence after the insertion sorting algorithm iterates a certain number of times is: the already ordered part + the second half of the same sequence as the original sequence.

Consider the merge sort again. The merge sort is ordered at least in each small unit. For example, after the first iteration, every two must be from small to large, and after the second iteration, every four must be from small to Large, but must we find the largest small unit?

Let's first determine whether it is an insertion sort through the above description.

int ifInsertSort(ElementType ASource[], ElementType ASort[], int N) {
	int i = N - 1;
	for (;i >= 0;i--) {
		if (ASort[i] != ASource[i])break;
	}
	int j = 0;
	for (;j < N-1;j++) {
		if (ASort[j] > ASort[j + 1]) {
			break;
		}
	}
	if (j > i) {
		return 1;//是插入排序
	}
	else {
		return 0;//不是插入排序
	}
}

But considering that the output is the result of another iteration , this method is not feasible . Because we can't judge from this method what iterating again looks like.

Now we can only use a stupid way: iterate in two ways separately, and then judge whether it is the same as the output every time.

We first create three arrays:

ElementType myArray[MaxVertexNum];//存原数据,插入排序用
ElementType myArray_1[MaxVertexNum];//存原数据,归并排序用
ElementType myArray2[MaxVertexNum];//存第二行数据

For insertion sort, we judge this way:

void InsertionSort(ElementType A[], int N)
{ 
	// 插入排序 
	int P, i;
	ElementType Tmp;
	int flag = 0;
	for (P = 1; P<N; P++) {
		Tmp = A[P]; // 取出未排序序列中的第一个元素
		for (i = P; i>0 && A[i - 1]>Tmp; i--)
			A[i] = A[i - 1]; //依次与已排序序列中元素比较并右移
		A[i] = Tmp; // 放进合适的位置 
		if (flag == 1)break;
		if (isSame(A, myArray2, N)) {
			flag = 1;
			isInsertFlag = 1;
			cout << "Insertion Sort"<<endl;
		}
	}
}

After the execution, it is judged whether the sequence of the current sort is the same as the sequence of the second line we read in . If the sequence is the same, the flag is set to 1. When judging flag = 1, it has been iterated again, so break.

At the same time, we also have a flag, isInsertFlag, to determine whether it is an insert sort. If it is always different, it is not an insert sort .

	InsertionSort(myArray, N);//插入排序
	if (isInsertFlag) {	
		for (int i = 0;i < N - 1;i++)
			cout << myArray[i] << " ";
		cout << myArray[N - 1];
	}	
	else if (!isInsertFlag) {
		cout << "Merge Sort" << endl;
		Merge_Sort(myArray_1, N);
		for (int i = 0;i < N - 1;i++)
			cout << myArray_1[i] << " ";
		cout << myArray_1[N - 1];
	}

The above code is used to determine whether it is insertion sort or merge sort.

In the merge sort we judge this way:

int isMerge = 0;
void Merge_Sort(ElementType A[], int N)
{
	int length;
	ElementType *TmpA;

	length = 1; // 初始化子序列长
	TmpA = (ElementType*)malloc(N * sizeof(ElementType));
	if (TmpA != NULL) {
		while (length < N) {
			Merge_pass(A, TmpA, N, length);
			if (isMerge == 1) {
				for (int ii = 0;ii < N;ii++)A[ii] = TmpA[ii];
				break;
			}
			if (isSame(TmpA, myArray2, N)) {
				isMerge = 1;
			}

			length *= 2;
			Merge_pass(TmpA, A, N, length);
			if (isMerge == 1) {
				break;
			}
			if (isSame(TmpA, myArray2, N)) {
				isMerge = 1;
			}
			length *= 2;
		}
		free(TmpA);
	}
	else printf("空间不足");
}

Because each while loop is actually merged twice, one is merged into A, and the other is merged into TmpA, so it must be processed separately.

The complete code is as follows:

#include <iostream>
using namespace std;

#define MaxVertexNum 105   //最大100个数据,多留出5个空白
typedef int ElementType;
ElementType myArray[MaxVertexNum];//存原数据,插入排序用
ElementType myArray_1[MaxVertexNum];//存原数据,归并排序用
ElementType myArray2[MaxVertexNum];//存第二行数据

int isInsertFlag = 0;
bool isSame(ElementType A[], ElementType B[], int N) {
	for (int i = 0;i < N;i++) {
		if (A[i] != B[i])return false;
	}
	return true;
}


void InsertionSort(ElementType A[], int N)
{ 
	// 插入排序 
	int P, i;
	ElementType Tmp;
	int flag = 0;
	for (P = 1; P<N; P++) {
		Tmp = A[P]; // 取出未排序序列中的第一个元素
		for (i = P; i>0 && A[i - 1]>Tmp; i--)
			A[i] = A[i - 1]; //依次与已排序序列中元素比较并右移
		A[i] = Tmp; // 放进合适的位置 
		if (flag == 1)break;
		if (isSame(A, myArray2, N)) {
			flag = 1;
			isInsertFlag = 1;
			cout << "Insertion Sort"<<endl;
		}
	}
}

// 归并排序 - 递归实现 
// L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置
void Merge(ElementType A[], ElementType TmpA[], int L, int R, int RightEnd)
{ // 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列
	int LeftEnd, NumElements, Tmp;
	int i;

	LeftEnd = R - 1; // 左边终点位置 
	Tmp = L;         // 有序序列的起始位置 
	NumElements = RightEnd - L + 1;

	while (L <= LeftEnd && R <= RightEnd) {
		if (A[L] <= A[R])
			TmpA[Tmp++] = A[L++]; // 将左边元素复制到TmpA 
		else
			TmpA[Tmp++] = A[R++]; // 将右边元素复制到TmpA 
	}

	while (L <= LeftEnd)
		TmpA[Tmp++] = A[L++]; // 直接复制左边剩下的 
	while (R <= RightEnd)
		TmpA[Tmp++] = A[R++]; // 直接复制右边剩下的 

	for (i = 0; i < NumElements; i++, RightEnd--)
		A[RightEnd] = TmpA[RightEnd]; // 将有序的TmpA[]复制回A[] 
}
// 归并排序 - 循环实现 
// 这里Merge函数在递归版本中给出 
// length = 当前有序子列的长度

void Merge_pass(ElementType A[], ElementType TmpA[], int N, int length)
{ // 两两归并相邻有序子列 
	int i, j;

	for (i = 0; i <= N - 2 * length; i += 2 * length)
		Merge(A, TmpA, i, i + length, i + 2 * length - 1);
	if (i + length < N) // 归并最后2个子列
		Merge(A, TmpA, i, i + length, N - 1);
	else // 最后只剩1个子列
		for (j = i; j < N; j++) TmpA[j] = A[j];

}
int isMerge = 0;
void Merge_Sort(ElementType A[], int N)
{
	int length;
	ElementType *TmpA;

	length = 1; // 初始化子序列长
	TmpA = (ElementType*)malloc(N * sizeof(ElementType));
	if (TmpA != NULL) {
		while (length < N) {
			Merge_pass(A, TmpA, N, length);
			if (isMerge == 1) {
				for (int ii = 0;ii < N;ii++)A[ii] = TmpA[ii];
				break;
			}
			if (isSame(TmpA, myArray2, N)) {
				isMerge = 1;
			}

			length *= 2;
			Merge_pass(TmpA, A, N, length);
			if (isMerge == 1) {
				break;
			}
			if (isSame(TmpA, myArray2, N)) {
				isMerge = 1;
			}
			length *= 2;
		}
		free(TmpA);
	}
	else printf("空间不足");
}

int main(void) {
	int N;cin >> N;
	for (int i = 0;i < N;i++) {
		cin >> myArray[i];
		myArray_1[i] = myArray[i];
	}
		
	for (int i = 0;i < N;i++)
		cin >> myArray2[i];

	InsertionSort(myArray, N);//插入排序
	if (isInsertFlag) {	
		for (int i = 0;i < N - 1;i++)
			cout << myArray[i] << " ";
		cout << myArray[N - 1];
	}	
	else if (!isInsertFlag) {
		cout << "Merge Sort" << endl;
		Merge_Sort(myArray_1, N);
		for (int i = 0;i < N - 1;i++)
			cout << myArray_1[i] << " ";
		cout << myArray_1[N - 1];
	}

	system("pause");
	return 0;
}



Test Results:

Published 187 original articles · praised 418 · 10,000+ views

Guess you like

Origin blog.csdn.net/tiao_god/article/details/105499321