c++ 一维数组(包括排序与例题)

一、一维数组的知识

扩:setw(输出的宽度) C++ 中的格式化函数,用于指定输出流的宽度。不能用于输入流

一维数组:一组相同类型的变量

格式:类型标识符 数组名[常量表达式]; eg: int a[5];

-- 类型标识符(基本数据类型/结构体等构造类型)

引用数组格式:数组名[下标]

eg: h[5]、h[i*2+1]等。

注意1:下标只能为整型常量或整型表达式 √√√

-- 整型表达式而不是整形变量 √√√

注意二:下标值必须在数组定义的下标范围内

注意三:不能一次引用整个数组,只能逐个引用数组的单个元素。

注意四:单输出数组名,返回数组的首地址

sizeof会返回数据类型的(字节)大小 int = 4字节 =(4*8)32位 1字节 = 1字符 = 1/2汉字 √√√

eg:int a[3]={1,2,3};

int b=12;

cout << sizeof(a) << endl;

cout << sizeof(b) << endl;

system("pause") -- 暂停程序的执行(暂停命令行窗口) 目的:为了查看程序的结果/错误信息

数组在计算机内存单元中是连续存储的

数组的插入思路:从最后开始往后移动直到插入后的位置逐步加一,然后开始插入x √√√

数组的删除思路:从删除的位置之后开始往前i减一(直接进行覆盖,不用再删除) √√√

数组的查找x:

查找操作的结果:可能是一个没找到、找到一个或者找到很多个

常见的查找:顺序查找和二分查找

顺序查找:按照从前往后的顺序,将数组中的元素依次与要查找的数x进行比较。

二分查找(折半查找):√√√

要求:数据是递增或递减排序的。

left right mid=(left+right)/2 循环:mid跟查找x比较,找到输出位置;

若没找到,若在左面,right=mid-1,若在右面,left=mid+1

优点:比较次数少、查找速度快。

数组的排序问题:通过数组中的元素比较和交换来实现的,关键是数组下标的分析 √√√

选择排序:从小到大:假设一个最小的,依次每个与最小的进行比较(获取最小的) 放在第一个位置(依次放到第二个位置.... )

冒泡排序:从小到大:每一轮依次两两进行比较,大的交换到后面(依次第二后,第三后...)

插入排序:

思想:把所有待排序元素分成前后两段,前一段是已经排好序的,后一段是待排序的。

每一趟都是把后一段的第一个数"插入"到前一段的某一个位置,保证前一段仍然是有序的。

开始时,第 1 个数作为前一段肯定是有序的;第一趟,把第 2 个数插入进去,保证前 2个数有序;

第二趟,把第 3 个数插入进去,保证前 3 个数有;......第 n-1 趟,把第 n 个数插入进去,保证 n 个数都有序。

二、数组的整体赋值

整体赋值(统一赋值):给数组按字节整体赋值,按元素整体赋值:

fill(d,d+5,8); //给d数组的前5个元素赋值为8

memset(c,0,5); //给数组前5个字节都赋值为 0

memset(b,1,sizeof(b)); //将b数组所有元素均赋值,按照sizeof(int) = 4字节 = 每一字节按8位计算2^0+2^8+2^16+2^24

示例:

#include<iostream>

#include<cstring>

#include<algorithm>

using namespace std;

int main(){

int a[10],b[10],c[10],d[10],i;

memset(a,0,sizeof(a)); // 将a数组所有元素均赋值为0

for(i = 0; i < 9; i++) cout << a[i] << " " ;

cout << a[9] << endl;

memset(b,1,sizeof(b));// 将 b 数组所有元素均赋值

//二进制数 2^0+2^8+2^16+2^24=16843009

for(i = 0; i < 9; i++) cout << b[i] << " " ;

cout << b[9] << endl;

memset(c,0,5);

//将 c 数组前 5 个字节都赋值为 0,所以只能确定 c[0]

//等于0,其他元素值不确定

for(i = 0; i < 9; i++) cout << c[i] << " " ;

cout << c[9] << endl;

fill(d,d+5,8);

//将 d 数组前 5 个元素都赋值为 8,其他元素值不确定

for(i = 0; i < 9; i++) cout << d[i] << " " ;

cout << d[9] << endl;

return 0;

}

三、下楼梯问题

【问题描述】

一个楼梯有 n 级,小苏同学从下往上走,一步可以跨一级,也可以跨两级。问:他走到第 n 级楼梯有多少种走法?

【输入格式】

一行一个整数 n,0<n≤30。

【输出格式】

一行 n 个整数,之间用一个空格隔开,表示走到第 1 级、第 2 级、......第 n 级分别有多少种走法。

【输入样例】

2

【输出样例】

1 2

【问题分析】

假设 f (i) 表示走到第 i 级楼梯的走法,则走到第 i (i>2)级楼梯有两种可能:一种是从第 i-1级楼梯走过来;另一种是从第 i-2 级楼梯走过来。

根据加法原理,f (i) = f (i-1) + f (i-2),边界条件为:f (1) = 1,f (2) = 2。

具体实现时,定义一维数组 f,用赋值语句从前往后对数组的每一个元素逐个赋值。本质上,f (i) 构成了斐波那契数列

解法:

#include<cstdio>

using namespace std;

int main(){

int n,i,f[31];

scanf( " %d " ,&n);

f[1] = 1; f[2] = 2;

for(i = 3; i <= n; i++) f[i] = f[i-1] + f[i-2];

for(i = 1; i < n; i++) printf( " %d ",f[i]);

printf( " %d\n " ,f[n]);

return 0;

}

四、幸运数问题:

【问题描述】

判断一个正整数 n 是否能被一个"幸运数"整除。幸运数是指一个只包含 4 或 7 的正整数,如 7、47、477 等都是幸运数,17、42 则不是幸运数。

【输入格式】

一行一个正整数 n,1≤n≤1000。

【输出格式】

一行一个字符串,如果能被幸运数整除输出"YES";否则,输出"NO"。

【输入样例】

47

【输出样例】

YES

【问题分析】

分析发现,1~1000 范围内的幸运数只有 14 个。于是,将这 14 个幸运数直接存储到一个数组 lucky 中,再穷举判断其中有没有一个数能整除 n。

代码:

//p5-2-3

#include<cstdio>

using namespace std;

int main(){

int n,lucky[14] = {4,7,44,47,74,77,444,447,474,477,744,747,

774,777};// 在数组定义时给数组赋值

scanf( " %d " , &n);

bool flag = false;

for(int i = 0; i < 14; i++)

if(n % lucky[i] == 0) flag = true;

if(flag) printf( " YES\n " );

else printf( " NO\n " );

return 0;

}

五、插队问题(数组的插入x):

(数组的插入)思路:从最后开始往后移动,直到插入后的位置,然后开始插入

【问题描述】

有 n 个人(每个人有一个唯一的编号,用 1~n 之间的整数表示)在一个水龙头前排队准备接水,

现在第 n 个人有特殊情况,经过协商,大家允许他插队到第 x 个位置。输出第 n 个人插队后的排队情况。

【输入格式】

第一行 1 个正整数 n,表示有 n 个人,2<n≤100。

第二行包含 n 个正整数,之间用一个空格隔开,表示排在队伍中的第 1~ 第 n 个人的编号。

第三行包含 1 个正整数 x,表示第 n 个人插队的位置,1≤x<n。

【输出格式】

一行包含 n 个正整数,之间用一个空格隔开,表示第 n 个人插队后的排队情况。

【输入样例】

7

7 2 3 4 5 6 1

3

【输出样例】

7 2 1 3 4 5 6

【问题分析】

n个人的排队情况可以用数组 q 表示,q[i]表示排在第 i 个位置上的人。

定义数组时多定义一个位置,然后重复执行:q[i+1] = q[i],其中,i 从 n ~ x。

最后再执行 q[x] = q[n+1],输出 q[1] ~ q[n]。

代码:

#include<cstdio>

using namespace std;

int main(){

int n,i,x,q[102];

scanf( " %d " ,&n);

for(i = 1; i <= n; i++) scanf( " %d " ,&q[i]);

scanf( " %d " ,&x);

for(i = n; i >= x; i--) q[i+1] = q[i];

q[x] = q[n+1];

for(i = 1; i < n; i++) printf( " %d " ,q[i]);

printf( " %d\n " ,q[n]);

return 0;

}

六、队伍调整:有一个人离开队伍(数组的删除x)

【问题描述】

有 n 个人(每个人有一个唯一的编号,用 1~n 之间的整数表示)在一个水龙头前排队准备接水,现在第 x 个人有特殊情况离开了队伍,求第 x 个人离开队伍后的排队情况。

【输入格式】

第一行 1 个正整数 n,表示有 n 个人,2<n≤100。

第二行包含n个正整数,之间用一个空格隔开,表示排在队伍中的第1个到第n个人的编号。

第三行包含 1 个正整数 x,表示第 x 个人离开队伍,1≤x≤n。

【输出格式】

一行包含 n-1 个正整数,之间用一个空格隔开,表示第 x 个人离开队伍后的排队情况。

【输入样例】

7

7 2 3 4 5 6 1

3

【输出样例】

7 2 4 5 6 1

代码:

#include<cstdio>

using namespace std;

int main(){

int n,i,x,q[102];

scanf( " %d " ,&n);

for(i = 1; i <= n; i++) scanf( " %d " ,&q[i]);

scanf( " %d " ,&x);

for(i = x; i < n; i++) q[i] = q[i+1];

n--;

for(i = 1; i < n; i++) printf( " %d " ,q[i]);

printf( " %d\n " ,q[n]);

return 0;

}

七、数组的二分查找:

int left = 0,right = n - 1;

int find = n;//find标记找到的位置,初始化为n,表示没找到

while(left <= right){

int mid = (left + right) / 2;

if(a[mid] == x){//找到了,就标记位置,并退出循环

find = mid;

break;

}

if(x < a[mid]) right = mid - 1;//x只能在左半部分

if(a[mid] < x) left = mid + 1; //x只能在右半部分

}

if(find != n) printf("%d\n",find);

else printf("not find\n");

八、选择排序(从小到大):

选择排序的基本思想是:每一趟从待排序的数据中,通过"打擂台"比较选出最小元素,放在这些数据的最前面。

这样,第一趟把 n 个数中(第 1 个到第 n 个)最小的放在第一个位置,

第二趟把剩余的 n-1 个数中(第 2 个到第 n 个)最小的放在第二个位置,

第三趟把剩余的 n-2 个数中(第 3 个到第 n 个)最小的放在第三个位,......

第 n-1 趟把剩下的 2 个数中(第 n-1 个到第 n 个)最小的放在第 n-1 个位置,

剩下的最后一个数(第 n 个)一定最大,自然落在了第 n个位置。

选择排序代码:(从小到大)

#include<iostream>

using namespace std;

int main(){

int n,i,j,k,temp,h[101];

cin >> n;

for(i = 1; i <= n; i++) cin >> h[i];

for(i = 1; i <= n; i++){

k = i; // 定义k为最小的位置

for(j = i+1; j <= n; j++)

if(h[j] < h[k]) k = j;// 在 i~n 之间的最小元素

temp = h[i];

h[i] = h[k]; // 把最小的放到第一个位置i ,依次第二个位置...

h[k] = temp;// 将 i~n 之间的最小元素放到第 i 个位置

}

for(i = 1; i < n; i++) cout << h[i] << " " ;

cout << h[n] << endl;

return 0;

}

九、冒泡排序(从小到大):

冒泡排序的基本思想是:从第一个数开始,依次不断比较相邻的两个元素,如果"逆序"就交换。

这样,一趟排序结束后,最大的元素就放在了第 n 个位置了。

第二趟把剩余的前 n-1 个数中最大的交换到第 n-1 个位置,

第三趟把剩余的前 n-2 个数中最大的交换到第 n-2 个位置,......

经过 n-1 趟,排序结束。

冒泡排序代码:(从小到大)

#include<iostream>

using namespace std;

int main(){

int n,i,j,temp,h[101];

cin >> n;

for(i = 1; i <= n; i++) cin >> h[i];

for(i = 1; i < n; i++)

for(j = 1; j <= n-i; j++)

if(h[j] > h[j+1]){

temp = h[j];

h[j] = h[j+1];

h[j+1] = temp;

}

for(i = 1; i < n; i++) cout << h[i] << " " ;

cout << h[n] << endl;

return 0;

}

十、对于冒泡排序,我们还可以做些算法"优化"。

如果一趟排序下来,都没有任何"逆序"数对,即没有发生"交换"操作,

则说明已经排好序了。此时,就可以立刻退出循环。

优化后的冒泡排序:

#include<iostream>

using namespace std;

int main(){

int n,i,j,temp,h[101];

cin >> n;

for(i = 1; i <= n; i++) cin >> h[i];

for(i = 1; i < n; i++){

bool flag = true;

for(j = 1; j <= n-i; j++)

if(h[j] > h[j+1]){

temp = h[j];

h[j] = h[j+1];

h[j+1] = temp;

flag = false;

}

if(flag) break;

}

for(i = 1; i < n; i++) cout << h[i] << " " ;

cout << h[n] << endl;

return 0;

}

十一、插入排序(从小到大):

插入排序的基本思想是:把所有待排序元素分成前后两段,前一段是已经排好序的,后一段是待排序的。

每一趟都是把后一段的第一个数"插入"到前一段的某一个位置,保证前一段仍然是有序的。

开始时,第 1 个数作为前一段肯定是有序的;第一趟,把第 2 个数插入进去,保证前 2个数有序;

第二趟,把第 3 个数插入进去,保证前 3 个数有;......

第 n-1 趟,把第 n 个数插入进去,保证 n 个数都有序。

插入排序的代码(从小到大):

#include<iostream>

using namespace std;

int main(){

int n,i,j,k,temp,h[101];

cin >> n;

for(i = 1; i <= n; i++) cin >> h[i];

for(i = 2; i <= n; i++){

temp = h[i];

k = 1;

while(h[k] <= temp && k < i) k++;

for(j = i-1; j >= k; j--) h[j+1] = h[j];

h[k] = temp;

}

for(i = 1; i < n; i++) cout << h[i] << " " ;

cout << h[n] << endl;

return 0;

}

相关推荐
唐诺5 小时前
几种广泛使用的 C++ 编译器
c++·编译器
冷眼看人间恩怨6 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客6 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin6 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
yuanbenshidiaos7 小时前
c++---------数据类型
java·jvm·c++
十年一梦实验室8 小时前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
taoyong0018 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我588 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
fpcc8 小时前
跟我学c++中级篇——C++中的缓存利用
c++·缓存
呆萌很8 小时前
C++ 集合 list 使用
c++