#Cprove 26~27 数组与函数应用

  • NO.1 有序数组中插入数据(函数版)
  • NO.2 删除数组元素
  • NO.3 数组的排序
  • NO.4 查成绩

NO.1 有序数组中插入数据(函数版)

有一个足够“大”的数组a,其中已经存储了n个呈升序排列的数据。调用函数insert(a, n, m),可以将数m插入到a中的合适位置,使其仍然保持升序,并且返回值为数组中有效数字的个数(即原先的n加1)。
例如,若a中数据为1 7 8 17 23 24 59 62 101,n=9,需要插入的数字m为50,调用函数insert(a, n, m)后,a中数据为1 7 8 17 23 24 50 59 62 101,n=10。

#include<stdio.h>
#define N 20
int insert(int a[],int,int);
int main()
{
    int a[N]={1, 7, 8, 17, 23, 24, 59, 62, 101};
    int i, n=9;
    int m =50;
    n = insert(a, n, m);   //在长度为n的a数组中插入m,使仍保持有序
    for(i=0; i<n; ++i)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}
int insert(int a[],int n,int x)
{
    int i=n;
    while(a[i-1]>x)
    {
        a[i]=a[i-1];
        i--;
    }
    a[i]=x;
    return n+1;
}
执行结果

在这里插入图片描述

小结

本例中a[i]=a[i-1]; i--不可合并为a[i--]=a[i-1],不然会影响结果。

NO.2 删除数组元素

del函数的作用是删除数组a中的指定元素x,n为数组a的元素个数。函数的返回值,为删除元素后的有效元素个数(数组中可能有重复元素)。函数的原型为:
int del (int a[10],int n,int x)
(1)请实现这个函数,并完成测试。
(2)如果在函数调用时,要求数组中的元素呈升序排列呢?

代码一
#include<stdio.h>
#define N 20
int del(int a[],int,int);
int main()
{
    int a[N]={1, 7, 8, 50, 50, 24, 50, 59, 62, 101};
    int i, n=10;
    int m =50;
    n = del(a, n, m);   //在长度为n的a数组中删除m
    for(i=0; i<n; ++i)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}
int del(int a[],int n,int x)
{
    int i,j=0;
    for(i=0;i<n;i++)
        if(a[i]!=x)     //把不等于x的数放入数组,也就排除了x
            a[j++]=a[i];
    return j;
}
执行结果

在这里插入图片描述

小结一:

排除的数只有一个元素,那直接用元素前移法比较好;但如果排除的数是多个并且可能有相同元素时,直接提取非排除元素更好;思维不要被前移法固定了,总是去找那些要排除的元素,有时候逆向思维更方便。

代码二
#include<stdio.h>
#define N 20
int del(int a[],int,int);
int main()
{
    int a[N]={1, 7, 8, 24, 50, 50, 50, 59, 62, 101};
    int i, n=10;
    int m =50;
    n = del(a, n, m);   //在长度为n的a数组中删除m
    for(i=0; i<n; ++i)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}
int del(int a[],int n,int x)    //排除升序数组a[n]中的元素x
{
    int *p=a,i;
    for(i=0;i<n;i++)
    {
        if(a[i]==x)     //指针指向第一个排除的元素单元
        {
            p=&a[i];
            break;
        }
    }
    while(p<a+n)
    {
        if((*p)!=x)     //将排除元素后面的数据前移
           a[i++]=*(p++);
        else
            p++;
    }
    return i;
}
执行结果

在这里插入图片描述

小结二

程序优化,当要删除的数不存在时,添加个输出语句,在del函数中的for循环结束后添加以下语句:

if(i>=n)
    {
        printf("no number!\n");
        return i;
    }

NO.3 数组的排序

(1)编写函数,完成冒泡排序
要求不能改变下面的main函数。

//两个函数bubble_sort和output_array的声明
   
int main( )
{
    int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
    int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
    bubble_sort(a,20);   //用冒泡法按降序排序a中元素
    output_array(a,20);   //输出排序后的数组
    bubble_sort(b,15);   //用冒泡法按降序排序b中元素
    output_array(b,15);   //输出排序后的数组
    return 0;
}
//请在下面定义bubble_sort和output_array函数

(2)字符数组排序:改造(1)的程序,使其能对字符数组进行排序

int a[20]={...};
int b[15]={...};

改为

char a[20] = {'s','o','r','t','b','u','b','b','l','e','s','e','l','e','c','t','o','k','o','k'};
char b[15] = {'a','b','a',...};  //自己补足

(3)体验选择排序:改造(1)的程序,将bubble_sort(…)改为select_sort(…),排序算法由冒泡排序换作为选择排序,排序结果由降序变为升序,完成类似的任务。

代码一
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void bubble_sort(int a[],int);
void output_array(int a[],int);

int main( )
{
    int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
    int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
    bubble_sort(a,20);   //用冒泡法按降序排序a中元素
    output_array(a,20);   //输出排序后的数组
    bubble_sort(b,15);   //用冒泡法按降序排序b中元素
    output_array(b,15);   //输出排序后的数组
    return 0;
}
//请在下面定义bubble_sort和output_array函数
void bubble_sort(int a[],int n)
{
    int i,j,t;
    for (i=0;i<n-1;i++)
        for(j=0;j<n-1-i;j++)
            if(a[j]<a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
}
void output_array(int a[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
    printf("\n");
}
执行结果一:

在这里插入图片描述

代码二
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void bubble_sort(char a[],int);
void output_array(char a[],int);

int main( )
{
    char a[20] = {'s','o','r','t','b','u','b','b','l','e','s','e','l','e','c','t','o','k','o','k'};
    char b[15] = {'a','b','a','b','c','l','u','o','e','p','s','i','l','o','n'};

    bubble_sort(a,20);   //用冒泡法按降序排序a中元素
    output_array(a,20);   //输出排序后的数组
    bubble_sort(b,15);   //用冒泡法按降序排序b中元素
    output_array(b,15);   //输出排序后的数组
    return 0;
}
//请在下面定义bubble_sort和output_array函数
void bubble_sort(char a[],int n)
{
    int i,j;
    char t;
    for (i=0;i<n-1;i++)
        for(j=0;j<n-1-i;j++)
            if(a[j]<a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
}
void output_array(char a[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%c ",a[i]);
    printf("\n\n");
}
执行结果二

在这里插入图片描述

代码三
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void select_sort(int a[],int);
void output_array(int a[],int);

int main( )
{
    int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
    int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
    select_sort(a,20);   //用选择排序法按升序排序a中元素
    output_array(a,20);   //输出排序后的数组
    select_sort(b,15);   //用选择排序法按升序排序b中元素
    output_array(b,15);   //输出排序后的数组
    return 0;
}
//请在下面定义bubble_sort和output_array函数
void select_sort(int a[],int n)
{
    int i,j,k,t;
    for (i=0;i<n-1;i++)     //n个元素需扫描n-1趟
    {
        k=i;
        for(j=i+1;j<n;j++)  //从i+1个开始遍历到结尾,需循环n-i-1次
            if(a[j]<a[k])
                k=j;
        t=a[k];
        a[k]=a[i];
        a[i]=t;
    }
}
void output_array(int a[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
    printf("\n");
}
执行结果三

在这里插入图片描述

NO.4 查成绩

(1)score1.txt提供了某大学两个班某次测验的数据,包括每位同学的学号及成绩。
请编程序,输入学号,查找出该同学的成绩。
提示1:可以定义两个int型数组,其中一个n存放学号,另一个s存放成绩,可以保证两个数组中,元素下标相同,对应的是同一位同学。例如n[18]值为3123,s[18]为98,说明学号为3123的同学成绩为98。
提示2:因为数据无序,运用顺序查找算法,在n数组中依据学号进行查找,在s数组中对应下标的值则为其成绩。例如,通过在n中的查找,得出学号为3123的同学的下标为18,则其成绩为s[18]。

#include<stdio.h>
#include<stdlib.h>
int readData(int [], int []);
int search(int [], int , int);
int main()
{
    int num[200], score[200];  //分别保存学号和成绩
    int count;  //代表学生人数
    int index;  //代表查找到的学生的下标
    int key;
    count = readData(num, score);   //将成绩数据从文件中读到数组中
    printf("请输入要查找的学生学号:");
    scanf("%d",&key);
    index = search(num, count, key);  //在count个学生中查找学号为key的学生对应的下标
    if(index<0)    //输入的学号不存在时,index的值要求返回-1
        printf("不存在学号为%d的同学\n",key);
    else
        printf("学号为%d的同学的成绩是:%d\n", key, score[index]);
    return 0;
}
int readData(int a[], int b[])  //读取文件数据分别存入两个数组
{
    int i=0;
    FILE *fp;
    if((fp=fopen("score1.txt","r"))==NULL)  //只读打开
    {
        printf("Can not open file!\n");
        exit(1);
    }
    while(!feof(fp))    //读取文件数据
    {
        fscanf(fp,"%d %d",&a[i],&b[i]);
        i++;
    }
    fclose(fp);
    return i;
}
int search(int a[], int n, int x)   //查询a[n]中元素x,返回下标
{
    int i;
    for(i=0;i<n;i++)
    {
        if(a[i]==x)
            return i;
    }
    if(i>=n)
        return -1;
    return 0;
}
执行结果

在这里插入图片描述
(2)在实际工程中,为了让频繁执行的查询更快一些,常要求对数据进行排序,再进行查询。请改造程序:①在调用readData(num, score);读入数据后,立即调用自定义函数sort对两个数组进行排序(注意在排序需要交换时,应该同时交换两个数组中对应的值,以保证同一下标,对应的是同一个学生的学号和成绩);②这样,search函数可以实现为二分查找了;③改造main函数,支持多次的查找。

#include<stdio.h>
#include<stdlib.h>
int readData(int [], int []);
void sort(int a[], int n, int b[]);
int search(int [], int, int);
int main()
{
    int num[200], score[200];  //分别保存学号和成绩
    int count;  //代表学生人数
    int index;  //代表查找到的学生的下标
    int key;
    int go_on;  //继续查找标志
    count = readData(num, score);   //将成绩数据从文件中读到数组中
    do
    {
        printf("\n请输入要查找的学生学号:");
        scanf("%d",&key);
        index = search(num, count, key);  //在count个学生中查找学号为key的学生对应的下标
        if(index<0)    //输入的学号不存在时,index的值要求返回-1
            printf("不存在学号为%d的同学\n",key);
        else
            printf("学号为%d的同学的成绩是:%d\n", key, score[index]);
        printf("\n输入1继续,输入其他值退出...");
        scanf("%d",&go_on);
    }
    while(go_on==1);  //输入1继续
    return 0;
}
int readData(int a[], int b[])  //读取文件数据分别存入两个数组
{
    int i=0;
    FILE *fp;
    if((fp=fopen("score1.txt","r"))==NULL)  //只读打开
    {
        printf("Can not open file!\n");
        exit(1);
    }
    while(!feof(fp))    //读取文件数据
    {
        fscanf(fp,"%d %d",&a[i],&b[i]);
        i++;
    }
    fclose(fp);
    sort(a,i,b);    //同时对数组a[i]和b[i]排序,此处i变量相当于n
    return i;
}
void sort(int a[], int n, int b[])  //对a[n]和b[n]同时排序,其中a[n]和b[n]为一一对应关系
{
    int j,k,t;
    for(j=0; j<n-1; j++)
        for(k=0; k<n-1-j; k++)
            if(a[k]>a[k+1])
            {
                t=a[k];
                a[k]=a[k+1];
                a[k+1]=t;

                t=b[k];
                b[k]=b[k+1];
                b[k+1]=t;
            }
}
int search(int a[], int n, int x)   //查询a[n]中元素x,返回下标
{
    int i;
    for(i=0; i<n; i++)
    {
        if(a[i]==x)
            return i;
    }
    if(i>=n)
        return -1;
    return 0;
}

执行结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值