PAT甲组1089&1098-排序迭代问题的思路与注意点--补充《算法笔记》

A1089
A1098
这两个题目思路基本相同,但本人之前做A1089时思路非常荒唐,今天做A1098看着题目很熟悉,但是思路还是不清晰,参考之前正确的解题思路才完成A1098

个人思路

A1089

警示作用,切勿参考

  • 判断:当时自己细细分析了插排和归并的“规律”,发现插排是前面有序,后面无序;归并是每组之内有序。以此作为判断条件来解题(纯粹模拟题的思路!!!),随后意识到要是归并的组内元素个数比插排的有序部分长怎么办???人傻了
  • 输出:在当前基础上只编写下一步代码
    跟正确解题思路一比,感觉个人思路完全没有过脑子,拿到题目便按着应该如何如何的想法思路下去,即想当然,不会分析问题,只是看到一步操作实现一步操作而已

本题思路

  • 先对初始序列进行插入排序操作,每迭代一次便于当前序列作比较,相同说明是插排,走到最后发现仍然不动说明是归并或者堆排序
  • 若是插排,输出下一次迭代结果跳出迭代即可。若是其他排序,找到与当前序列吻合的一次迭代,输出下一次迭代的结果,跳出迭代即可

A1089的AC代码

#include <bits/stdc++.h>
using namespace std;
int n;
int origi[105];
int origi2[105];
int first[105];
bool sortFlag = false;//false:归并,true:插入 
bool judge(int a[], int b[])
{
	for(int i = 0; i < n; i++)
	{
		if(a[i] != b[i])
		{
			return false;
		}
	}
	return true;
}
void display(int a[])
{
	for(int i = 0; i < n; i++)
	{
		printf("%d", a[i]);
		if(i < n - 1)
		{
			printf(" ");
		}
	}
	printf("\n");
}
void insertSort(int a[])
{ 
	int tempn = n; 
	for(int i = 1; i < tempn; i++)
	{
		int temp = a[i], j = i;
		while(j > 0 && temp < a[j - 1])
		{
			a[j] = a[j - 1];
			j--;
		}
		a[j] = temp;
		if(judge(a, first))//数组一致
		{
			tempn = i + 2;
			sortFlag = true;
		}
		else
		{
			continue;
		}
	}
}
void mergeSort(int a[])
{
	int tempn = n;
	for(int step = 2; step / 2 <= tempn; step *= 2)
	{
		for(int i = 0; i < n; i += step)
		{
			sort(a + i, a + min(i + step, n));
		}
		if(judge(a, first))
		{
			tempn = step;
		}
		else
		{
			continue;
		}
	}
}
int main(int argc, char *argv[]) {
	scanf("%d", &n);
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &origi[i]);
		origi2[i] = origi[i];
	}
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &first[i]);
	}
	insertSort(origi);
	if(sortFlag)
	{
		printf("Insertion Sort\n");
		display(origi);
	}
	else
	{
		printf("Merge Sort\n");
		mergeSort(origi2);
		display(origi2);
	}
	return 0;
}

A1098的AC代码

与上一题略有不同的是,此题要求升序排列,根据堆排序每次将第一个元素与最后一个元素交换位置以确定最后一个位置元素的顺序。因此在堆排序前,应该建立大顶堆,才能经过堆排序完成升序序列
PS:可以对每一个元素进行sort排序来替代插排

#include <bits/stdc++.h>
using namespace std;
int N;
int origin[105], current[105], heap[105];
bool flag;//false:堆排序,true:插排 
bool check(int a[], int b[])
{
	for(int i = 1; i <= N; ++i)
	{
		if(a[i] != b[i])
			return false;
	}
	return true;//序列相吻合 
}
void insertSort()
{
	for(int i = 2; i <= N; ++i)
	{
		int temp = origin[i];//当前插入元素 
		int j = i;
		while(j > 1 && temp < origin[j - 1])
		{
			origin[j] = origin[j - 1];
			j--;
		}
		origin[j] = temp;
		if(flag)
			break;
		if(check(origin, current))
		{
			flag = true;
		}
	}
}
void downAdjust(int low, int high)
{
	int father = low, lchild = father * 2, rchild = father * 2 + 1;
	while(lchild <= high)
	{
		//大顶堆 
		if(rchild <= high && heap[rchild] > heap[lchild])
			lchild = rchild;
		if(heap[lchild] > heap[father])
		{
			swap(heap[lchild], heap[father]);
			father = lchild;
			lchild = father * 2;
			rchild = father * 2 + 1;
		}
		else
			break;
	}
}
void heapSort()
{
	bool isCur = false;
	for(int i = N; i > 1; i--)
	{
		if(isCur)
			break;
		if(check(heap, current))
			isCur = true;
		swap(heap[i], heap[1]);
		downAdjust(1, i - 1);
	} 
}
int main(int argc, char *argv[]) {
	scanf("%d", &N);
	for(int i = 1; i <= N; ++i)
	{
		scanf("%d", &origin[i]);
		heap[i] = origin[i];
	}
	for(int i = 1; i <= N; ++i)
	{
		scanf("%d", &current[i]);
	}
	insertSort();
	if(flag)
	{
		printf("Insertion Sort\n");
		for(int i = 1; i <= N; ++i)
		{
			printf("%d", origin[i]);
			if(i < N)
				printf(" ");
		}
	}
	else
	{
		printf("Heap Sort\n");
		for(int i = N / 2; i >= 1; i--)//建堆 
		{
			downAdjust(i, N);
		}
		heapSort();
		for(int i = 1; i <= N; ++i)
		{
			printf("%d", heap[i]);
			if(i < N)
				printf(" ");
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值