1.选择排序
基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在待排序的数列的最前面,直到全部待排序列的数据排完
#include<bits/stdc++.h>
using namespace std;
int main() {
int i, j, k, n;
double a[10001], temp;
cin >> n;
for ( i = 1; i <= n; i++) {
cin >> a[i];;
}
for (i = 1; i <= n; i++) {
k = i;
for (j = i + 1; j <= n; j++) {
if (a[j] < a[k]) {
k = j;
}}
if (k != i) {
temp = a[i]; a[i] = a[k]; a[k] = temp;
}
}
for ( i = 1; i <= n; i++) {
cout << a[i] << " ";
}
return 0;
}
2.冒泡排序
每轮将n个数据的排序规模转化成n-1,每两两间比较
改进:对于有些数据,并不一定需要排那么多次数,可以设置一个布尔类型的数据作为判断标志
#include<bits/stdc++.h>
using namespace std;
const int MAX = 10001;
bool flag;
int main() {
int n, i, j;
double a[MAX],temp;
cin >> n;
for (i = 1; i <= n; i++) {
cin >> a[i];
}
for ( i = 1; i <= n-1; i++) {
flag = true;
for (j = 1; j <= n - i; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
flag = false;
}
}
if(flag){
break;
}
for (int i = 1; i <= n; i++) {a
cout << a[i] << " ";
}
return 0;
}
车厢重组问题: 有两行数据,第一行是车厢总数N(不大于10000),第二行是N个不同的数表示初始的车厢顺序。输出最少旋转次数
#include<bits/stdc++.h>
using namespace std;
int main() {
int i, j, k, n,count =0;
double a[10001], temp;
bool flag ;
cin >> n;
for ( i = 1; i <= n; i++) {
cin >> a[i];;
}
for (i = 1; i <= n-1; i++) {
flag = true;
for (j = 1; j <= n - i; j++) {
if (a[j] > a[j + 1]) {
swap(a[j], a[j + 1]);
count++;
flag = false;
}
if (flag) {
break;
}
}
}
cout << count << endl;
return 0;
}
插入排序
当读入一个数据时,在已排序好的序列中,搜寻它正确的位置,再放入读入读入的元素。但不该忽略一个重要的问题:在插入这个元素前,应当先将它后面的所有元素后移一位,以保证插入位置的原元素不被覆盖
#include<bits/stdc++.h>
using namespace std;
int main() {
int len;
double a[101];
cin >> len;
for (int i = 1; i <= len; i++) {
cin >> a[i];
}
for (int j = 1; j <= len; j++)
{
int key = a[j];
int i = j - 1;
while (i >= 0 && a[i] > key)
{
a[i + 1] = a[i];
i--;
}
a[i + 1] = key;
}
for (int i = 1; i <= len; i++) {
cout << a[i] << " ";
}
return 0;
}
桶排序
若待排序的值在一个明显有限范围内时,可设计有限个有序桶,待排序的值装入对应的桶,桶号就是待排序的值,顺序输出各桶内的值,将得到有序的序列
#include<bits/stdc++.h>
using namespace std;
int a[1001], b[1001];
int main() {
int k;
cin >> k;
for (int i = 1; i <= k; i++) {
cin >> a[i];
b[a[i]]++;
}
for (int i = 1; i <= 1001; i++) {
while (b[i] > 0) {
cout << i << " ";
b[i]--;
}
}
return 0;
}
明明的随机数:有2行,第1行为1个正整数,表示所生成的随机数个数:N; 第2行有N个用空格隔开的正整数,为所产生的随机数。
#include<bits/stdc++.h>
using namespace std;
int b[1001];
int main() {
int k,t,count=0;
cin >> k;
for (int i = 1; i <= k; i++) {
cin >> t;
if (b[t]==0) {
b[t]++;
count++;
}
}
cout << count << endl;
for (int i = 1; i <= 1001; i++) {
if (b[i] != 0) {
cout << i << " ";
}
}
return 0;
}
快速排序:是对冒泡排序的一种改进
基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键词小,则可分别对这两部分记录继续进行排序,以达到整个序列有序
#include<bits/stdc++.h>
using namespace std;
int get_mid(int b[], int left, int right) {
int pivot = b[left];
while (left < right) {
while (b[right] >= pivot && left < right)
{ right--;}
b[left] = b[right];
while (b[left] <= pivot && left < right)
{left++;}
b[right] = b[left];
b[left] = pivot;
}
return left;
}
void quick_sort(int b[], int left, int right) {
if (left < right) {
int mid = get_mid(b, left, right);
quick_sort(b, left, mid - 1);
quick_sort(b, mid + 1, right);
}
}
int main() {
int c[10] = { 6,3,17,9,8,7,5,12,23,11 };
quick_sort(c, 0, 9);
for (int i = 0; i < 10; i++) {
cout << c[i] << " ";
}
return 0;
}
int finding(int l,int r,int k)
{
if(l==r) return a[l];
int i=l,j=r;
int mid=(l+r)>>1;
int x=a[mid];
while(i<=j)
{
while(a[j]>x) j--;
while(a[i]<x) i++;
if(i<=j)
{
swap(a[i],a[j]);
i++,j--;
}
}
if(k<=j) return finding(l,j,k);
else if(k>=i) return finding(i,r,k);
else return a[k];
}
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
归并排序:建立在归并操作的一种有效算法,该算法是采用分治算法的典型应用
#include<bits/stdc++.h>
using namespace std;
int a[1001], c[1001];
void msort(int left, int right) {
if (left == right) { return; }
int mid = (left + right) / 2;
int i = left, j = mid + 1, k = left;
msort(left, mid);
msort(mid + 1, right);
while (i <= mid && j <= right) {
if (a[i] <= a[j]) {
c[k] = a[i]; k++; i++;
}
else {
c[k] = a[j]; k++; j++;
}
}
while (i <= mid) {
c[k] = a[i]; k++; i++;
}
while (j <= right) {
c[k] = a[j]; k++; j++;
}
for (int i = left; i <= right; i++) {
a[i] = c[i];
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
msort(1, n);
for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
return 0;
}
逆序对问题:对与给定的叔祖数列,求其逆序对数量(主要归并排序)
#include<bits/stdc++.h>
using namespace std;
int a[5] = { 3,1,4,5,2 };
int c[5], ans;
void msort(int left, int right) {
if (left == right) { return; }
int mid = (left + right) / 2;
int i = left; int j = mid + 1, k = left;
msort(left, mid);
msort(mid+1, right);
while(i <= mid && j <= right) {
if (a[i] <= a[j]) {
c[k] = a[i]; k++; i++;
}
else {
c[k] = a[j]; k++;j++;
ans += mid - i + 1;
cout << endl;
cout << ans << endl;
}
}
while (i <= mid) {
c[k] = a[i]; k++; i++;
}
while (j <= right) {
c[k] = a[j]; k++; j++;
}
for (int i = left; i <= right; i++) {
a[i] = c[i];
}
}
int main() {
msort(0, 4);
for (int i = 0; i <= 4; i++) {
cout << a[i]<<" ";
}
cout << endl;
cout << "共计" << ans << "对逆序对" << endl;
return 0;
}
1.谁考了第k名
#include<bits/stdc++.h>
using namespace std;
struct student {
int id;
int score;
};
student a[1001];
int get_mid(student a[], int left, int right) {
int pivot = a[left].score;
while (left < right) {
while (a[right].score > pivot && left < right) {
right--;
}
a[left].score = a[right].score;
while (a[left].score < pivot && left < right) {
left++;
}
a[right].score = a[left].score;
a[left].score = pivot;
}
return left;
}
void quick_sort(student a[],int left,int right) {
if (left < right) {
int mid = get_mid(a, left, right);
quick_sort(a, left, mid);;
quick_sort(a, mid + 1, right);
}
}
int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i].id>> a[i].score;
}
quick_sort(a, 1, n);
cout << a[k].id << " " << a[k].score;
return 0;
}
2.奇数单增数列
#include<bits/stdc++.h>
using namespace std;
int a[10001];
int get_mid(int a[], int left, int right) {
int pivot = a[left];
while (left < right) {
while (a[right] >= pivot && left < right) {
right--;
}
a[left] = a[right];
while (a[left] <= pivot && left < right) {
left++;
}
a[right] = a[left];
a[left] = pivot;
}
return left;
}
void quick_sort(int a[], int left, int right) {
if (left < right) {
int mid = get_mid(a, left, right);
quick_sort(a, left, mid);
quick_sort(a, mid + 1, right);
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
quick_sort(a, 1, n);
for (int i = 1; i <= n; i++) {
if(a[i]/2!=0){
cout << a[i] << " ";
}
}
return 0;
}
3.*成绩排序,分数相同则字典序小在前
记
return a.score > b.score || a.score == a.score && strcmp(a.name, b.name) < 0;作为字典序和数值判断函数
#include<bits/stdc++.h>
using namespace std;
int n;
struct stu {
int score;
char name[20];
};
stu a[1001];
bool is_prior(stu &a,stu &b) {
return a.score > b.score || a.score == a.score && strcmp(a.name, b.name) < 0;
//成绩和字典序判断
}
void bubble_sort(stu a[]) {
for (int i = 1; i <= n - 1; i++) {
for (int j = 1; j <= n - i; j++) {
if (is_prior(a[j+1],a[j])) {
swap(a[j+1],a[j]);
}
}
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].name>>a[i].score;
}
bubble_sort(a);
for (int i = 1; i <= n; i++) {
cout << a[i].name << " " << a[i].score << endl;;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct Stu
{
char name[25];
int score;
};
bool isPrior(Stu &a, Stu &b)//a是否应该排在b的前面
{
return a.score > b.score || a.score == b.score && strcmp(a.name, b.name) < 0;
}
int main()
{
Stu stu[25];
int n;
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> stu[i].name >> stu[i].score;
for(int i = 1; i <= n-1; ++i)//冒泡排序
for(int j = 1; j <= n-i; ++j)
if(isPrior(stu[j+1], stu[j]))//如果stu[j+1]应该在stu[j]前面
swap(stu[j], stu[j+1]);
for(int i = 1; i <= n; ++i)
cout << stu[i].name << ' ' << stu[i].score << endl;
return 0;
}
4.奖学金Noip2007
题目描述
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:
包含n+1行:
第1行为一个正整数n(小于300),表示该校参加评选的学生人数。
第2到n+1行,每行有3个用空格隔开的数字,每个数字都在0到100之间。第j行的3个数字依次表示学号为 j−1 的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1∼n (恰好是输入数据的行号减1)。
共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。
#include<bits/stdc++.h>
using namespace std;
int n;
struct stu {
int id;
int yuwen, shuxue, yingyu;
int sum = yuwen + shuxue + yingyu;
};
stu a[100];
bool is_prior(stu &p,stu &q) {
if (p.sum > q.sum) {
return true;
}
if (p.sum == q.sum && p.yuwen > q.yuwen) {
return true;
}
if (p.sum == q.sum && p.yuwen == q.yuwen && p.id < q.id) {
return true;
}
return false;
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].yuwen >> a[i].shuxue >> a[i].yingyu;
a[i].id = i;
a[i].sum = a[i].shuxue + a[i].yingyu + a[i].yuwen;
}
for (int i = 1; i <= n - 1; i++) {
for (int j = 1; j <= n - i; j++) {
if (is_prior(a[j + 1], a[j])) {
swap(a[j + 1], a[j]);
}
}
}
for (int i = 1; i <= 5; i++) {
cout << a[i].id << " " << a[i].sum<<endl;
}
return 0;
}
5.整数奇偶排列
#include<bits/stdc++.h>
using namespace std;;
int a[11], b[10], c[10];
int indexb, indexc;
void sort(int a[]) {
for (int i = 1; i <= 10; i++) {
if (a[i] % 2 != 0) {
indexb++;
b[indexb] = a[i];
}
else {
indexc++;
c[indexc] = a[i];
}
}
}
int main() {
for (int i = 1; i <= 10; i++) {
cin >> a[i];
}
sort(a);
for (int i = 1; i <= indexb - 1;i++) {
for (int j = 1; j <=indexb - i; j++) {
if (b[j] < b[j + 1]) {
swap(b[j], b[j + 1]);
}
}
}
for (int i = 1; i <= indexc-1; i++) {
for (int j = 1; j <= indexc - i; j++) {
if (c[j] > c[j + 1]) {
swap(c[j + 1], c[j]);
}
}
}
for (int i = 1; i <= indexb; i++) {
cout << b[i] << " ";
}
for (int i = 1; i <= indexc; i++) {
cout << c[i] << " ";
}
return 0;
}
6.单词排序
记
while (cin >> w[n].word) {
n++;
}
n--;//最后一次输入的值是EOF,不是有效的值,n应该减1
使用此方法不断录入字符串 ctrl-+z+回车结束
#include<bits/stdc++.h>
using namespace std;
int n;
struct Word {
char word[50];
};
Word w[101];
bool is_prior(Word &a,Word &b) {
return strcmp(a.word, b.word) < 0;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> w[i].word;
}
for (int i = 1; i <= n - 1; i++) {
for (int j = 1; j <= n - i; j++) {
if (is_prior(w[j + 1], w[j])) {
swap(w[j + 1], w[j]);
}
}
}
for (int i = 1; i <= n; i++) {
if (strcmp(w[i].word, w[i+1].word) == 0) {
i++;
}
else {
cout << w[i].word << endl;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct Word {
char word[50];
};
Word w[101];
bool is_prior(Word &a,Word &b) {
return strcmp(a.word, b.word) < 0;
}
int main() {
int n = 1;
while (cin >> w[n].word) {
n++;
}
n--;//最后一次输入的值是EOF,不是有效的值,n应该减1
for (int i = 1; i <= n - 1; i++) {
for (int j = 1; j <= n - i; j++) {
if (is_prior(w[j + 1], w[j])) {
swap(w[j + 1], w[j]);
}
}
}
for (int i = 1; i <= n; i++) {
if (strcmp(w[i].word, w[i+1].word) == 0) {
i++;
}
else {
cout << w[i].word << endl;
}
}
return 0;
}
7.统计字符数
描述
给定一个由a-z这26个字符组成的字符串,统计其中哪个字符出现的次数最多。
【输入】
输入包含一行,一个字符串,长度不超过1000。
【输出】
输出一行,包括出现次数最多的字符和该字符出现的次数,中间以一个空格分开。如果有多个字符出现的次数相同且最多,那么输出ascii码最小的那一个字符。
—
#include<bits/stdc++.h>
using namespace std;
int main() {
char st[128];
int cs[128] = {0};
cin >> st;
int len = strlen(st);
int max = 0;
for (int i = 0; i < len; i++) {
cs[st[i]]++;
}
for (int i = 0; i < 128; i++) {
if (cs[i] >cs[max]) {
max = i;
}
}
cout << char(max) << " " << cs[max];
return 0;
}