自学内容网 自学内容网

插入与冒泡排序(C++)

\一、插入排序

1 简介

插入排序,也称为直接插入排序,其排序思想和我们平时打扑克牌时排序类似。

2 算法步骤

将第一个元素看作已排序序列,第二个到最后一个看作未排序序列。

第二个元素,与之前已排序号的序列进行对比,插入正确的位置(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

循环处理剩下的未排序序列。

效果图:

2.png

3 复杂度

当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较N- 1次,最优时间复杂度为O(n)

最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(n^2)

空间复杂度为O(1)

4 稳定性

稳定的,数据的相对顺序不会发生改变。

5 代码实现:略

二、冒泡排序

1 简介

冒泡排序(Bubble sort),是一种简单的排序算法。

它重复地循环要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

2 算法步骤

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

效果图:

1.png

3 复杂度

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 和记录移动次数 均达到最小值: 所以,冒泡排序最好的时间复杂度为O(n)。

若初始文件是反序的,需要进行n-1趟排序。每趟排序要进行n-i次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

冒泡排序的最坏时间复杂度为O(n^2)

综上,因此冒泡排序总的平均时间复杂度为O(n^2)

空间复杂度为O(1)

4 稳定性

冒泡排序是稳定排序,不会改变数据的大小相对位置;

5 代码实现:略

第1题     插入排序(程序填空)

输入N个整数,使用插入排序法从小到大输出。

输入格式

第一行1个正整数:N,范围在[1,1000]。
第二行N个整数,每个整数范围在[0,1000000]。

输出格式

一行N个从小到大的整数。

输入/输出例子1

输入:


5 3 6 1 

输出:

1 3 5 6 

输入/输出例子2

输入:

4
5 5 1 9

输出:

1 5 5 9

第1空:

a[i]

第2空:

a[k]<temp

第3空:

a[j+1]=a[j]

第1题     冒泡排序(程序填空)

输入N个整数,使用冒泡排序法从小到大输出。

输入格式

第一行1个正整数:N,范围在[1,1000]。
第二行N个整数,每个整数范围在[0,1000000]。

输出格式

一行N个从小到大的整数。

输入/输出例子1

输入:


5 3 6 1 

输出:

1 3 5 6 

输入/输出例子2

输入:

4
5 5 1 9

输出:

1 5 5 9

 第1空

n-i

第2空

a[j]>a[j+1]

第3空

a[j]

第4空

a[j+1]

第1题     插入排序 查看测评数据信息

输入N个整数,使用插入排序法从小到大输出。

输入格式

第一行1个正整数:N,范围在[1,1000]。
第二行N个整数,每个整数范围在[0,1000000]。

输出格式

一行N个从小到大的整数。

输入/输出例子1

输入:


5 3 6 1 

输出:

1 3 5 6 

输入/输出例子2

输入:

4
5 5 1 9

输出:

1 5 5 9

 

#include<bits/stdc++.h>
using namespace std;
long long n,i,j,k,temp,a[100005];
int main(){    
    cin>>n;
    for(i=1;i<=n;i++)cin>>a[i];
    for(i=2;i<=n;i++){
        temp=a[i];
        k=1;
        while(a[k]<temp&&k<i){
            k++;
        }
        for(j=i-1;j>=k;j--){
            a[j+1]=a[j];
        }
        a[k]=temp;
    }
    for(i=1;i<=n;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}

第2题     冒泡排序 查看测评数据信息

输入N个整数,使用冒泡排序法从小到大输出。

输入格式

第一行1个正整数:N,范围在[1,1000]。
第二行N个整数,每个整数范围在[0,1000000]。

输出格式

一行N个从小到大的整数。

输入/输出例子1

输入:


5 3 6 1 

输出:

1 3 5 6 

输入/输出例子2

输入:

4
5 5 1 9

输出:

1 5 5 9

#include<bits/stdc++.h>
using namespace std;
long long n,i,j,a[100005];
int main(){
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    for(i=1;i<n;i++){
        for(j=1;j<=n-i;j++){
            if(a[j]>a[j+1]){
                swap(a[j],a[j+1]);
            }
        }
    }
    for(i=1;i<=n;i++){
        cout<<a[i]<<" ";
    }
    
    return 0;
}

第3题     排名(rank) 查看测评数据信息

期中考试后,陈老师想对同学们的成绩进行排名。共有 n 名同学,按成绩从高到低进行排名,同分的同学排名相同。陈老师希望你能帮他把名次排出来。

输入格式

第一行一个正整数,n。

第二行 n 个用空格隔开的范围为[0..100]的整数,表示 n 名同学的成绩。

输出格式

n 行,每行两个正整数,分别表示一个成绩和该成绩的排名,从高到低的输出。

输入/输出例子1

输入:

10

89 83 88 84 85 88 87 85 90 88

输出:

90 1

89 2

88 3

88 3

88 3

87 6

85 7

85 7

84 9

83 10

样例解释

【数据范围】

100%的数据 1<=n<=100

#include<bits/stdc++.h>
using namespace std;
long long n,i,j,k,temp,a[100005],b[100005];
int main(){
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    for(i=1;i<n;i++){
        for(j=1;j<=n-i;j++){
            if(a[j]<a[j+1]){
                swap(a[j],a[j+1]);
            }
        }
    }
    for(i=1;i<=n;i++){
        b[i]=i;
    }
    for(i=1;i<n;i++){
        if(a[i]==a[i+1]){
            b[i+1]=b[i];
        }
    }
    for(i=1;i<=n;i++){
        cout<<a[i]<<" "<<b[i]<<'\n';
    }
    return 0;
}

第4题     交换次数 查看测评数据信息

输入N个整数,如果每次只能交换相邻的2个数,要把数组从小到大排序,至少需要交换几次?

输入格式

第一行1个正整数:N,范围在[1,1000]。
第二行N个整数,每个整数范围在[0,1000000]。

输出格式

一行N个从小到大的整数。

输入/输出例子1

输入:


5 3 6 1 

输出:

4

#include<bits/stdc++.h>
using namespace std;
long long n,i,j,a[100005],s;
int main(){
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    for(i=1;i<n;i++){
        for(j=1;j<=n-i;j++){
            if(a[j]>a[j+1]){
                swap(a[j],a[j+1]);
                s++;
            }
        }
    }
    cout<<s;
    return 0;
}

第5题     兔子 查看测评数据信息

明明家养了N只兔子,边上种植了很多胡萝卜。平时兔子都被关在一个大笼子里,每天明明喂每只兔子3根胡萝卜。
某天饿疯了的兔子们咬坏了笼子门,跑到地里尽情地吃起胡萝卜。每只兔子的“吃货值”不一样,已知第i只兔子每分钟吃Ei个胡萝卜。
明明1分中后发现了情况,急忙开始捉拿这些兔子,已知明明每分钟可以捉一只,请问明明怎样捉才能使得被兔子吃最少的胡萝卜。计算出被兔子吃最少胡萝卜的个数。
例如:N=2, E1=4,E2=5;明明第1个捉第2个兔子(这个兔子已经吃了5根胡萝卜),第2个捉第1个兔子(这个兔子已经吃了8根胡萝卜),共被兔子吃了13根胡萝卜。

输入格式

第一行: 1 个正整数 N。N的范围[1…10000]
第二行 N 个正整数: 表示 N 只兔子每分钟可以吃的胡萝卜数,每个数的范围[1…1000000]。

输出格式

一个整数,表示最少要被吃掉多少胡萝卜。

输入/输出例子1

输入:


2 1 3 

输出:

10 

#include<bits/stdc++.h>
using namespace std;
bool f(int a,int b){
return a>b;
}
long long n,a[100005],h=0,t=0,s=0;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+n,f);
    for(int i=1;i<=n;i++){
        t++;
    s=s+a[i]*t;
    }
    cout<<s;
    return 0;
}

第6题     第K小数 knumber 查看测评数据信息

现有n个正整数,n<=10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k<=1000,正整数均小于30000。 

输入格式

第一行为n和k,第二行开始为n个正整数的值,整数间用空格隔开。

输出格式

第k个最小正整数的值;若无解,则输出“NO RESULT”。

输入/输出例子1

输入:

10 3 
1 3 3 7 2 5 1 2  4 6

输出:

3

#include<bits/stdc++.h>
using namespace std;
int n,a[1000005],k;
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    int len=unique(a+1,a+n+1)-a;
    if(k<len)cout<<a[k];
    else cout<<"NO RESULT";
    return 0;
}

第7题     火柴 (GCOI2015五4) 查看测评数据信息

有N根火柴,第i根火柴的长度是Li。小明很喜欢正方形,所以小明希望用这些火柴拼出尽量多的正方形,但要同时满足如下条件:

1、一根火柴最多只能用在一个正方形中。

2、组成正方形的四根火柴,长度必须都相同。

给出N根火柴的长度,你的任务是计算:最多可以拼出多少个正方形?

输入格式

第一行,一个整数N。
第二行,N个整数,第i个整数是Li。

输出格式

一个整数,表示最多能拼出的正方形的数量

输入/输出例子1

输入:

7
1  1  2  2  1  1  2

输出:

1

输入/输出例子2

输入:

20
1  2  3  4  1  2  3  4  1  2  3  1  2  3  4  1  2  3  3  3

输出:

3

样例解释

样例1解释:只能拼出1个正方形,正方形的边长是1。样例2解释:能拼出3个正方形,正方形的边长是1、2、3。

【数据规模】 对于60%的数据, 4 <= N <= 50, 1 <= Li <= 1000。 对于100的数据,4 <= N <= 5000,1 <= Li <= 1000000000。

#include<bits/stdc++.h>
using namespace std;
long long int a[500005],i,j,n,s=0,sum,b[500005];
int main(){
    scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b,b+n);
    long long m=0,k=1;
    while(k<n){
        if(b[k]!=b[m]) b[++m]=b[k];
        k++;
    }
    for(i=0;i<m+1;i++){    
sum=0;
        for(j=0;j<n;j++){
            if(b[i]==a[j])sum++;
        }
        s=sum/4+s;
    }
    printf("%d",s);
    return 0;

}

第8题     奖学金(scholar) 查看测评数据信息

某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。 

任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是: 

7 279

5 279 

这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是 279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是: 

5 279 

7 279 

则按输出错误处理,不能得分。

输入格式

输入数据包含n+1行: 

第1行为一个正整数n,表示该校参加评选的学生人数。 

第2到n+1行,每行有3个用空格隔开的数字,每个数字都在O到100之间。第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为l~n (恰好是输入数据的行号减1)。 

所给的数据都是正确的,不必检验。

输出格式

输出数据共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。

输入/输出例子1

输入:

6

90  67  80

87  66  91

78  89  91

88  99  77

67  89  64

78  89  98 

输出:

6  265

4  264

3  258

2  244

1  237

输入/输出例子2

输入:

8

80  89  89

88  98  78

90  67  80

87  66  91

78  89  91

88  99  77

67  89  64

78  89  98

输出:

8  265

2  264

6  264

1  258

5  258

样例解释

【限制】

50%的数据满足:各学生的总成绩各不相同;

100%的数据满足: 6≤n≤300。

#include<bits/stdc++.h>
using namespace std;
struct node{
int chinese,maths,English,zongfen,id;
}a[330];
int main(){
    int n,i,j;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i].chinese>>a[i].maths>>a[i].English;
        a[i].id=i;
        a[i].zongfen=a[i].chinese+a[i].maths+a[i].English;
    }
    for(i=n-1;i>=1;i--){
        for(j=1;j<=i;j++){    
if(a[j].zongfen<a[j+1].zongfen)swap(a[j],a[j+1]);
        else if((a[j].zongfen==a[j+1].zongfen)&&(a[j].chinese<a[j+1].chinese))swap(a[j],a[j+1]);    
        else if((a[j].zongfen==a[j+1].zongfen)&&(a[j].chinese==a[j+1].chinese)&&a[j].id>a[j+1].id)swap(a[j],a[j+1]);
        }
    }
    for(i=1;i<=5;i++)cout<<a[i].id<<" "<<a[i].zongfen<<endl;
    return 0;
}

第1题     分数线划定 (score) 查看测评数据信息

世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿者,则面试分数线为排名第m*150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手。

 现在就请你编写程序划定面试分数线,并输出所有进入面试的选手的报名号和笔试成绩。

提示:向下取整,即把小数部分去掉。例如:4.3和4.8向下取整都是4。

输入格式

第一行,两个整数n,m(5 ≤ n ≤ 5000,3 ≤ m ≤ n),中间用一个空格隔开,其中n 表示报名参加笔试的选手总数,m 表示计划录取的志愿者人数。输入数据保证m*150%向下取整后小于等于n。

 第二行到第 n+1 行,每行包括两个整数,中间用一个空格隔开,分别是选手的报名号k(1000 ≤ k ≤ 9999)和该选手的笔试成绩s(1 ≤ s ≤ 100)。数据保证选手的报名号各不相同。

输出格式

第一行,有两个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。

 从第二行开始,每行包含两个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。

输入/输出例子1

输入:

6 3

1000 90

3239 88

2390 95

7231 84

1005 95

1001 88

输出:

88 5

1005 95

2390 95

1000 90

1001 88

3239 88

#include<bits/stdc++.h>
using namespace std;
long long n,m,b[1000550],a[1000550],i,j,sum,ans=0;
int main(){
    cin>>n>>m;
    for(i=0;i<n;i++){
    cin>>b[i]>>a[i];
    }
    for(i=1;i<=n-1;i++){
        for(j=0;j<=n-i;j++){
            if(a[j]<a[j+1]){
                swap(a[j],a[j+1]);
                swap(b[j],b[j+1]);
            }
            if(a[j]==a[j+1]){
                if(b[j]>b[j+1]){
                    swap(a[j],a[j+1]);
                    swap(b[j],b[j+1]);
                }
            }
        }
    }
    m=double(m*1.5);
    sum=a[m-1];
    for(i=0;i<n;i++){
    if(a[i]>=sum)ans++;
        else break;
    }
    cout<<sum<<" "<<ans<<'\n';
    for(i=0;i<ans;i++){
    cout<<b[i]<<" "<<a[i]<<'\n';
    }
    return 0;

}

第2题     2015GCOI六5 最大数 查看测评数据信息

计时器游戏结束后,晨晨的同学明明取了其中的N个计时器设计出拼数字游戏:明明和晨晨各自把N个计时器排成一行,看谁拼出的数最大。例如:有N=3个计时器,上面数字分别是31,3,331,两人拼的方案分别是:

image.png

明明拼的数字是333131,晨晨拼的数字是331313,显然明明赢。明明掌握了拼出最大值的核心算法,晨晨下决心也要研究。

输入格式

第一行:1个整数N。

第二行N个整数:表示N个计时器上的数。

输出格式

一个整数,表示拼成的最大数字。

输入/输出例子1

输入:

3
31  3  331

输出:

333131

输入/输出例子2

输入:

8

73 1 3 776 12 225 4 936

输出:

9367767343225121

样例解释

30%的数据,n<=10,每个数<10^3
50%的数据,n<=100
100%的数据,n<=1000,每个数<10^200 

#include<bits/stdc++.h>
using namespace std;
string a[100005];
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(a[i]+a[j]<a[j]+a[i]){
swap(a[i],a[j]);  
}
}
}
for(int i=0;i<n;i++){
cout<<a[i];
}
return 0;
}

第3题     拯救花园(nhoixj2013) 查看测评数据信息

一天,晨晨发现自己的n(2≤n≤100)只兔子跑到自己的花园里面,它们在尽情的吃着她的宝贝花卉。晨晨看在眼里痛在心里,她现在只能把兔子逐个的抓回笼子里面。而送每只兔子回去的时间都不同,例如送第i只兔子回去需要ti(1≤ti≤100)单位时间,那么晨晨送第i只兔子来回共需要花费2*ti单位时间,另外每一只兔子单位时间的破坏力都不同,例如第i只兔子单位时间内破坏di (1≤di≤100)朵花。

现在的问题是,晨晨如何安排送这n只兔子回笼子才能使这些兔子的破坏最小。

输入格式

第一行:一个整数n(1≤n≤100);

接着有n行,每行两个空格分开的整数ti di,分别代表第i只兔子的送回去的时间,和单位时间破坏力。

输出格式

一行:一个整数,代表这些兔子破坏多少花卉。

输入/输出例子1

输入:

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

输出:

86

样例解释

样例解释:

    晨晨送兔子回去的顺序分别为:6, 2, 3, 4, 1, 5。其中先送第6只兔子回去,剩余兔子破坏(1+5+3+2+1)*2=24朵花;送第2只兔子回去,剩余兔子破坏(1+3+2+1)*4=28朵花;以此类推,送第3、4、1只兔子回去剩余兔子的破坏分别为16、12和6朵花;最后送第5只兔子回去的时候,没有兔子在花园里面了,所以破坏0朵花,最后总共破坏24 + 28 + 16 + 12 + 6 = 86朵花。

#include<bits/stdc++.h> 
using namespace std;
int n,x,s; 
struct str{
int s1,s2;
}a[1000005];
bool f(str q,str p){
return p.s1*q.s2<q.s1*p.s2;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].s2>>a[i].s1;
}
for(int i=1;i<=n;i++){
s+=a[i].s1;
}
sort(a+1,a+1+n,f);
for(int i=1;i<=n;i++){
s-=a[i].s1;
x+=s*a[i].s2*2;
}
cout<<x;
return 0;
} 

 制作不易,点个三连(#^.^#)


原文地址:https://blog.csdn.net/hjxxlsx/article/details/142416502

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!