CSP初赛复习-16排序-真题分析

1 NOIP2010 阅读程序

#include <iostream>
using namespace std;

void swap(int & a, int & b)//函数引用传值 引用是别名,函数内修改对应调用函数也会改变
{
    int t;
    t = a;
    a = b;
    b = t;
}

int main()
{
    int a1, a2, a3, x;
        
    cin>>a1>>a2>>a3;
    // 示例 5 4 3
    if (a1 > a2)
        swap(a1, a2);//a1>a2 交换 执行后 a1 < a2 变成4 5 3
    if (a2 > a3)
        swap(a2, a3);//a2>a3 交换 执行后a2<a3 变成4 3 5
    if (a1 > a2)
        swap(a1, a2);//a1>a2 交换 执行后 a1 < a2 变成3 4 5
    //此时 a1 a2 a3 从小到大排好序
    cin>>x;//输入x
    if (x < a2)//x<a2 
        if (x < a1) //x<a2 && x<a1 最小 插入最前面
            cout<<x<<' '<<a1<<' '<<a2<<' '<<a3<<endl;
        else//x<a2 && x>=a1 插入a1和a2之间
            cout<<a1<<' '<<x<<' '<<a2<<' '<<a3<<endl;
    else//x>=a2
        if (x < a3) //x>=a2 && x<a3 插入a2和a3直接
            cout<<a1<<' '<<a2<<' '<<x<<' '<<a3<<endl;
        else//x>=a3 插入a3后面
            cout<<a1<<' '<<a2<<' '<<a3<<' '<<x<<endl;    
    return 0;
}
/*
输入
91 2 20
77
*/

分析

此程序分两部分

1 对a1 a2 a3从小到大排序

2 把x插入到a1 a2 a3 合适位置,使得a1 a2 a3 x四个数从小到大排序

根据上面输入

91 2 20
77

因此对上面输入a1 a2 a3 x从小到大排序

输出

2 20 77 90

2 NOIP2010 阅读程序

#include<iostream>
using namespace std;
int main()
{
    const int SIZE=100;
    int na,nb,a[SIZE],b[SIZE],i,j,k;
    cin>>na;//输入一个数na
    for(i=1;i<=na;i++)//输入na个对应数字对a数组 -数组中从小到大有序
        cin>>a[i];
    cin>>nb;//输入一个数nb
    for(i=1;i<=nb;i++)//输入nb个对应数字到b数组 -数组中从小到大有序
        cin>>b[i];
    i=1;
    j=1;
    while( (i<=na)&&(j<=nb) )//i 1~na j 1~nb
    {    //如下判断每次在a,b两个数组中取最小的一个数输出
        if(a[i]<=b[j])//如果a[i]<=b[j] 输出a[i]
        {
            cout<<a[i]<<' ';
            i++;
        }
        else//输入b[j]<a[i] 输出b[j]
        {
            cout<<b[j]<<' ';
            j++;
        }
    }
    if(i<=na)//如果a数组没有输出完 把a数组未输出的数字输出
       for(k=i;k<=na;k++)
           cout<<a[k]<<' ';
    if(j<=nb)//如果b数组没有输出完 把b数组未输出的数字输出
       for(k=j;k<=nb;k++)
           cout<<b[k]<<' ';
    return 0;
}
/*
输入:
5
1 3 5 7 9
4
2 6 10 14
*/

分析

此程序类似归并排序的合并过程

while 循环输出a,b数组中较小的数

while循环结束,a数组还有数字未输出,输出5和7

3 NOIP2011 阅读程序

#include<iostream>
#include<cstring>
using namespace std;

const int SIZE = 100;

int main()
{
    int n,i,sum,x,a[SIZE];
    
    cin>>n;
    //sizeof(a)是数组大小*4(int 占4个字节) 由于前面定义数组元素为100,所以sizeof(a)=400
    memset(a,0,sizeof(a));//对数组进行初始0 按位初始二进制 
    
    for(i=1;i<=n;i++){
        cin>>x;
        a[x]++;//计数排序
    }
    i=0;
    sum=0;
    while(sum<(n/2+1)){
        i++;
        sum+=a[i];
    }
    cout<<i<<endl;
    return 0;
}
/*
输入:
11
4 5 6 6 4 3 3 2 3 2 1
*/

分析

通过计数排序对下列数放到对应数组中

11
4 5 6 6 4 3 3 2 3 2 1

根据计算排序对a数组初始数据结果如下

对代码进行分析

	i=0;
    sum=0;
    while(sum<(n/2+1)){//n/2+1=6
        i++;
        sum+=a[i];
    }
    cout<<i<<endl;

所以

i=0 sum=0 0<6 执行后 i=1 sum=1

i=1 sum=1 1<6 执行后 i=2 sum=1+2=3

i=2 sum=3 3<6 执行后 i=3 sum=3+3=6

i=3 sum=6 6<6不满足条件退出

所以i=3

4 NOIP2014 阅读程序

#include <stdio.h>
#include <string.h>
const int	SIZE	= 100;
const int	LENGTH	= 25;
/*
 * strcmp(a,b) <0:a的字典序小于b
 * strcmp(a,b) =0:a和b一样
 * strcmp(a,b) >0:a的字典序大于b
 */
int main()
{
	char	dict[SIZE][LENGTH + 1];
	int	rank[SIZE];
	int	ind[SIZE];
	int	i, j, n, tmp;
	scanf( "%d", &n );
	for ( i = 1; i <= n; i++ )
	{
		rank [i]	= i;//此行在后续排序没有使用 可以去除
		ind[i]		= i;//字符串的位置
		scanf( "%s", dict[i] );
	}
	for ( i = 1; i < n; i++ )//毛坯排序
		for ( j = 1; j <= n - i; j++ )
			if ( strcmp( dict[ind[j]], dict[ind[j + 1]] ) > 0 )
			{//交换位置
				tmp		= ind[j];
				ind[j]		= ind[j + 1];
				ind[j + 1]	= tmp;
			}
	for ( i = 1; i <= n; i++ )//使用类似计数排序安排对应位置
		rank[ind[i]] = i;
	for ( i = 1; i <= n; i++ )
		printf( "%d ", rank[i] );
	printf( "\n" );
	return(0);
}
/*
输入:
7
aaa
aba
bbb
aaa
aaa
ccc
aa
*/

模拟简单数据

3
aba	
bbb	
aaa

3个数冒泡排序,需要进行3-1=2趟

第1趟比较2次

第2趟比较1次

比较后顺序如下

把此顺序按数字下标放入rank排序数组,此思想类似计数排序

输出rank数组对应值,即

第1个aba排第2,第2个bbb排第3,第3个aaa排第1

CSP初赛复习-16-数据结构-排序-练习题
https://www.cnblogs.com/myeln/articles/17574468.html

posted @ 2023-07-24 23:43  new-code  阅读(56)  评论(0)    收藏  举报