冒泡相关问题
7-9 直接排序
7-10 输出元素在原来序列中的位置 → 对属性进行绑定, 对排序的属性排序的时候将其他属性一起交换 / 值当做下标(哈希)
7-12 先排序, 再找中位数
7-13 先分离每一位, 再对和排序 → 多组输入可能需要memset初始化
7-14 7-15 冒泡排序
7-16 选择排序
7-19 排序 + 思维
7-9 直接排序
#include <stdio.h>
int q[1010];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
for(int i = 1; i <= n - 1; i ++)
{
for(int j = 0; j < n - i; j++)
{
if(q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
}
}
}
for(int i = 0; i < n; i++) //注意控制行末空格
{
if(i) printf(" %d", q[i]);
else printf("%d", q[i]);
}
return 0;
}
7-10
//法一: 哈希 :
//数值q[i] → 位置 i + 1 如果q[i]的值太大(超过mp数组的大小或者q[i]的值为负数/浮点数, 不适用)
//mp[i]存的是当前的数值i在初始的时候的位置, i 为 数值
//mp[q[i]] 里面的i是下标
//注: 此题有负数数据, 哈希的方法最后一个点过不去
#include <stdio.h>
int mp[1000010]; //mp数组的大小根据q[i]的数组决定, 尽量开的大一些
int q[1010];
int main()
{
int n = 10;
for (int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
mp[q[i]] = i + 1;
}
for (int i = 1; i <= n - 1; i++)
{
for (int j = 0; j < n - i; j++)
{
if (q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
}
}
}
for (int i = 0; i < n; i++) // 注意控制行末空格
{
if (i)
printf(" %d", q[i]);
else
printf("%d", q[i]);
}
printf("\n");
for (int i = 0; i < n; i++)
{
if (i)
printf(" %d", mp[q[i]]); //因为数据里面有负数, 所以最后一个点过不去
else
printf("%d", mp[q[i]]);
}
return 0;
}
//法二: 把位置跟数值绑定在一起, 当交换数值的时候把位置一起交换(结构体)
//mp[i]存的是当前的第i个元素在初始的时候的位置, i 为 下标
#include <stdio.h>
int mp[100010];
int q[100010];
int main()
{
int n = 10;
for (int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
mp[i] = i + 1; //位置从1开始, 下标i从0开始
}
for (int i = 1; i <= n - 1; i++)
{
for (int j = 0; j < n - i; j++)
{
if (q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
t = mp[j];
mp[j] = mp[j + 1];
mp[j + 1] = t;
}
}
}
for (int i = 0; i < n; i++) // 注意控制行末空格
{
if (i)
printf(" %d", q[i]);
else
printf("%d", q[i]);
}
printf("\n");
for (int i = 0; i < n; i++)
{
if (i)
printf(" %d", mp[i]);
else
printf("%d", mp[i]);
}
return 0;
}
7-12 sdut-C语言实验- 中位数
#include <stdio.h>
int q[1010];
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
for(int i = 1; i <= n - 1; i++)
{
for(int j = 0; j < n - i; j++)
{
if(q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
}
}
}
double mid;
if (n % 2 == 0)
{
int pre = (n - 1) / 2; //下标
int post = pre + 1;
mid = (q[pre] + q[post]) / 2.0;
}
else
{
int pre = (n - 1) / 2; // 下标
mid = q[pre];
}
printf("%.1f\n", mid);
}
return 0;
}
7-13 sdut-C语言实验-各位数字之和排序
#include <stdio.h>
#include <string.h>
int q[55];
int sum[55]; //存的是分离q[i]的每一位求和后的值
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
memset(sum, 0, sizeof sum); // 多组输入可能需要用memset初始化, 头文件<string.h>
//int sum[55]; //可以把数组开在循环体里面, 但是如果太大的话容易栈空间不足, 因此更常用memset初始化
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
for(int i = 0; i < n; i++) //对q数组的每一个值分离每一位并求和操作
{
int tmp = q[i];
while(tmp)
{
int dig = tmp % 10;
sum[i] += dig; //如果不更新每一组的sum[i]的话, 前面已经加起来的结果会影响后面组的数据
tmp /= 10;
}
}
for(int i = 1; i <= n - 1; i ++)
{
for(int j = 0; j < n - i; j++)
{
if(sum[j] > sum[j + 1]) //排序的是 每一位的和 这个属性, 而输出的是原数组, 所以我们需要将原数组跟每一位的和的数组绑定
{
int t = sum[j];
sum[j] = sum[j + 1];
sum[j + 1] = t;
t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
}
}
}
int f = 0;
for(int i = 0; i < n; i++)
{
if(f == 0) f = 1;
else printf(" ");
printf("%d", q[i]);
}
printf("\n"); //多组输入一般要用\n
}
return 0;
}
7-14 sdut-C语言实验- 冒泡排序中数据交换的次数
#include <stdio.h>
int q[5050];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
int cnt = 0;
for(int i = 1; i <= n - 1; i ++)
{
for(int j = 0; j < n - i; j++)
{
if(q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
cnt++;
}
}
}
printf("%d\n", cnt);
}
return 0;
}
7-15冒泡排序
#include <stdio.h>
int q[5050];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
for (int i = 1; i <= n - 1; i++)
{
for (int j = 0; j < n - i; j++)
{
if (q[j] > q[j + 1])
{
int t = q[j];
q[j] = q[j + 1];
q[j + 1] = t;
}
}
int f = 0;
for(int j = 0; j < n; j++)
{
if(!f) f = 1;
else printf(" ");
printf("%d", q[j]);
}
printf("\n");
}
if(n == 1) printf("%d", q[0]); //因为这个题目输出是在排序里面, 所以当n = 1的时候(不需要排序的的时候)就没输出了, 需要特判
return 0;
}
7-16选择排序
#include <stdio.h>
int q[1101];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &q[i]);
}
for(int i = 1; i <= n - 1; i++)
{
int min = q[i - 1]; //待交换的数为区间的左端点
int pos = i - 1;
for(int j = i - 1; j <= n - 1; j++) //打擂法, 找区间的最小值[i - 1, n - 1]
{
if(q[j] < min)
{
min = q[j];
pos = j;
}
}
int t = q[pos]; //交换区间的左端点与当前区间的min
q[pos] = q[i - 1];
q[i - 1] = t;
int f = 0;
for(int j = 0; j < n; j++)
{
if(!f) f = 1;
else printf(" ");
printf("%d", q[j]);
}
printf("\n");
}
if(n == 1) printf("%d", q[0]);
return 0;
}
数组
考点
- 排序
- 冒泡排序 O(n^2)
- 选择排序 O(n^2)
- (插入排序)
- 分离每一位
- 正序
- 逆序
- 哈希(hash) → 用值直接作为下标
- 日期处理问题
- 数组的基本操作
- 插入和删除
- 逆序(移位)
- 7 - 19田忌赛马 (双指针)
- 二维数组 → 矩阵
- 矩阵转置
- 判断对称矩阵
- 矩阵运算
- 矩阵移位
- 杨辉三角
分离每一位
正序
//方法一: 当成字符串处理
hello world
char str[100];
scanf("%s", str); //遇到空格会断开
hello
gets(str);//读入一行
hello world
//遍历字符串的结束条件
如果用%s或者gets来读字符串, 字符串后面默认有一个'\0'
for(int i = 0; str[i] != '\0'; i++)
{
}
'\0' ascii码值为0 null
可以简写为
for(int i = 0; str[i]; i++)
{
}
#include <string.h>
strlen() 函数, 返回当前字符串'\0'前面的长度
for(int i = 0; i < strlen(str); i++)
字符串str里的每一个str[i]都是一个字符变量
'0' - '0' → 数字 0
'1' - '0' → 数字 1
通过 - '0' 可以将字符'0' ~ '9'转成数字 0 ~ 9
//方法二: 先建立一个逆序的数组, 倒着输出
先用分离每一位 → 逆序建一个数组
如果要求输出正序结果, 直接逆序遍历这个数组
int q[1010];//存逆序每一位的结果
int k = 0; //待分离的数的位数
int tmp; //tmp是要分离的数
while(tmp)
{
int dig = tmp % 10;
q[k++] = dig;
tmp /= 10;
}
//k表示位数, 3位 最后一个数下标为2, 遍历的话 k - 1开始
for(int i = k - 1; i >= 0; i--)
{
//正序的结果
}
逆序
int k = 0;
int q[100010];
while(tmp)
{
int dig = tmp % 10;
q[k++] = dig;
tmp /= 10;
}
//逆序遍历从k - 1开始
7-2 sdut-C语言实验-整数位
//逆序建立,顺序结果的话只需逆序遍历; 顺序建立, 逆序结果需要逆序遍历
#include <stdio.h>
int q[15];
int main()
{
int n;
scanf("%d", &n);
int k = 0;
while(n)
{
int dig = n % 10;
q[k++] = dig;
n /= 10;
}
printf("%d\n", k);
for(int i = k - 1; i >= 0; i--)
{
if(i == 0) printf("%d\n", q[i]);
else printf("%d ", q[i]);
}
for(int i = 0; i < k; i++)
{
if(i == 0) printf("%d", q[i]);
else printf(" %d", q[i]);
}
return 0;
}
哈希思想 → 数组存的是出现次数
用数组q[i]表示数值i的出现次数
注意限制条件:
- 如果数值i是负数或者浮点数不能直接用
- 如果数值i过大不能用(每一个元素的数值不能大于定义的q数组的大小)
7-5 sdut-C语言实验-众数
#include <stdio.h>
#include <string.h> //memset的头文件
int q[1010];
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
memset(q, 0, sizeof q); //多组输入的初始化, 上一组的q中数值不清空会影响下一组
for(int i = 0; i < n; i++)
{
int x;
scanf("%d" ,&x);
q[x]++; //q[x]存的是x的出现次数
}
int max = -1;
int max_count = 0; //众数与众数出现的次数是绑定的, 判断的是出现次数, 更新的是众数本身
for(int i = 0; i <= 1000; i++)
{
if(q[i] > max_count)
{
max_count = q[i];
max = i;
}
}
printf("%d\n", max);
}
return 0;
}
7-7 去掉重复的数据
#include <stdio.h>
int q[101100];
int main()
{
int n;
scanf("%d", &n);
int f = 0;
for(int i = 0; i < n; i++)
{
int x;
scanf("%d", &x);
if(q[x] == 0)
{
if(f == 0) f = 1;
else printf(" ");
q[x] = 1;
printf("%d", x); //注意是按照输入顺序而不是从小到大顺序, 一边读入一边处理输出即可
}
else continue;
}
return 0;
}