PAT A1089/B1035 Insert or Merge 与各种排序

PAT A1089/B1035 Insert or Merge

一、题意:
给出一个原始数列和一个经排序后的数列,判断是插入排序还是归并排序,并输出下一步排序后的数列。

分析:
要确定所给定的数列是插入排序后还是归并排序,需要将每次排序后的数列与原始数列比较,如果一样,则再经过一次排序即可。注意:这里如果给的两次都是原始数列,可能会有两种结果。如 3 4 2 1
3 4 2 1

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 111;
int origin[N], tempOri[N], changed[N];
int n;
bool isSame(int A[], int B[])
{
	for(int i = 0; i < n; i++)
	{
		if(A[i] != B[i])
		return false;
	}
	return true;
}
void showArray(int A[])
{
	for(int i = 0; i < n; i++)
	{
		printf("%d", A[i]);
		if(i < n-1)
		printf(" ");
	}
	printf("\n");
}
bool insertSort()
{
	bool flag = false;
	for(int i = 1; i < n; i++)
	{
		if(i != 1 && isSame(tempOri, changed))
		flag = true;//每次都样比较与目的数列是否一样
		
		int j = i, temp = tempOri[i];
		while(tempOri[j-1] > temp)
		{
			tempOri[j] = tempOri[j-1];
			j--;
		}
		tempOri[j] = temp;
		
		if(flag == true)
		return true;
	}
	
	return false;
}

void mergeSort()
{
	bool flag = false;
	for(int step = 2; step/2 <= n; step *= 2)
	{
		if(step != 2 && isSame(tempOri, changed))
		flag = true;
		
		for(int i = 0; i < n; i += step)
		{
			sort(tempOri + i, tempOri + min(i+step, n));
		}
		
		if(flag == true)
		{
			showArray(tempOri);
			return;
		}
	 } 
}

int main()
{
	scanf("%d", &n);
	for(int i = 0; i < n; i++)
	scanf("%d", &origin[i]);
	
	for(int i = 0; i < n; i++)
	scanf("%d", &changed[i]);
	
	for(int i = 0; i < n; i++)
	{
		tempOri[i] = origin[i];
	}
	
	if(insertSort())
	{
		printf("Insertion Sort\n");
		showArray(tempOri);
	}
	else
	{
		for(int i = 0; i < n; i++)
		{
			tempOri[i] = origin[i];
		}
		printf("Merge Sort\n");
		mergeSort();
	}
	
	return 0;
}

二、归并排序:
首先将数列两两分组,然后组内排序。之后再左右之间的分组组合在一起,再进行组内排序,直至分组长度大于等于数列长度。
在这里插入图片描述
1.递归实现:

const int maxn = 100;
void Merge(int A[], int L1, int R1, int L2, int R2)
{
	int i = L1, j = L2;
	int temp[maxn], index = 0;
	while(i <= R1 && j <= R2)
	{
		if(A[i] < A[j])
		temp[index++] = A[i++];
		if(A[i] >= A[j])
		temp[index++] = A[j++];
	}
	while(i <= R1)
	temp[index++] = A[i++];
	while(i <= R2)
	temp[index++] = A[j++];
}
void MergeSort(int A[], int left, int right)
{
	if(left < right)
	{
		int mid = (left + right)/2;
		MergeSort(A, left, mid);
		MergeSort(A, mid+1, right);
		Merge(A, left, mid, mid+1, right);
	}
}

2.非递归实现

void MergeSort(int A[], int left, int right)
{
	for(int step = 2; step /2 <= n; step *= 2)
	{//这里为step/2是因为当step = 2n的时候是整个数列(左子列)内的排序,而step = n的时候是对整个数列分成两分的左右子列分别排序
		for(int i = 0; i < n; i += step)
		{
			int mid = i + step/2-1;
			merge(A, i, mid, mid+1, mid+ min(i+step-1, n));
		}//这里i+step-1是为了防止越界
	}
}

为了方便,这里也可以直接用sort函数来代替merge函数。

三、插入排序
每次选出数列中的一个数,并按大小关系插入已经排好的部分数列中。
在这里插入图片描述

void insertSort(int A[])
{
	for(int i = 1; i < n; i++)//下标为0~n
	{
		int temp = A[i], j = i;//用一个数来暂时保存要排序的数的副本和下标,因为前面的数字有可能比它大,所以前面的数字可能会往后挪导致当前的数字可能被覆盖
		while(temp < A[j])
		{
			A[j] = A[j-1];
			j--;
		}
		A[j] = temp;//排序完后将原先要排序的数字放入属于它的位置
	}
}

三、选择排序
每次从数列中选出一个最小的数字,将其与最前面未排序的数字交换。
在这里插入图片描述

void SelectSort(int A[], int n)
{
	int temp, k;
	for(int i = 0; i < n-1; i++)
	{
		k = i;
		for(int j = i; j < n; j++)
		{
			if(A[j] < A[k])
			{
				A[k] = A[j];
				k = j;
			}
			temp = A[k];
			A[k] = A[i];
			A[i] = temp;
		}
	}
}
发布了17 篇原创文章 · 获赞 0 · 访问量 115

猜你喜欢

转载自blog.csdn.net/weixin_45486992/article/details/104907737
今日推荐