自学内容网 自学内容网

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;
}


原文地址:https://blog.csdn.net/xzal12/article/details/142945788

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