一维数组知识点与习题结合1

冒泡相关问题

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的出现次数
注意限制条件:

  1. 如果数值i是负数或者浮点数不能直接用
  2. 如果数值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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值