#Cprove20~21查找与排序

NO.1 简单冒泡排序

对比下标从0开始与从1开始的区别。
在这里插入图片描述

NO.2 二分法解方程

对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。
假设要求方程f(x)=0的解,给定精确度ξ。其算法是:

  1. 确定区间[a,b],验证f(a)·f(b)<0
  2. 求区间(a,b)的中点c
  3. 判断
    (1) 若f(a)·f(c)<0,则令b=c;
    (2) 若f(c)·f(b)<0,则令a=c.
  4. 判断f(c)是否达到精确度ξ:即若┃f(c)┃<ξ,则x=c就是使f(x)接近零点的近似值,否则重复2-4.

请按照上面的算法,编程序求解方程f(x)=2x^3-5x^2+3x-6=0,要求精确到0.00001.

#include <stdio.h>
#include<math.h>
double f(double x);
int main( )
{
    double a0,a,b0,b,c;    //定义区间[a0,b0],中点c
    do
    {
        printf("输入求根区间:");
        scanf("%lf %lf",&a0,&b0);
    }
    while(f(a0)*f(b0)>=0);    //保证函数值在[a0,b0]上异号
    a=a0;
    b=b0;
    c=(a+b)/2;
    while(fabs(f(c))>1e-5)
    {

        if(f(c)*f(a)<0)
            b=c;            //f(a),f(c)异号,把c给b
        else
            a=c;
        c=(a+b)/2;
    }
    printf("区间[%.2lf,%.2lf]根为:%.5lf",a0,b0,c);
    return 0;
}

double f(double x)
{
    double fx;
    fx=2*x*x*x-5*x*x+3*x-6;
    return fx;
}

执行结果
在这里插入图片描述

NO.3 有序数组中插入数据

定义好一个有10个元素的数组,先输入9个呈升序的数作为前9个元素,再输入一个数,要求按原来排序的规律将它插入数组中。
例如,9个呈升序的数为1 7 8 17 23 24 59 62 101,需要插入的数字为50,输出的序列则为1 7 8 17 23 24 50 59 62 101。

#include <stdio.h>
#define SIZE 5
int main( )
{
    int i,t,j,n,a[SIZE]= {0};
    printf("Input SIZE-1 num: ");
    for(i=0; i<SIZE-1; i++)        //对 SIZE-1 个数输入并排序
        scanf("%d",&a[i]);
    for(i=0; i<SIZE-2; i++)
        for(j=0; j<SIZE-2-i; j++)
        {
            if(a[j]>a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
        }
    printf("有序序列:\n");
    for(i=0;i<SIZE-1;i++)
        printf("%d ",a[i]);
    printf("\nInput n : ");
    scanf("%d",&n);
    //输入数n在序列范围内则插入到a[i+1]位置
    /**<
    //方案一
    if(n<a[0])          //输入数n小于序列最小数则放a[0]
    {
        for(j=SIZE-1; j>0; j--)
            a[j]=a[j-1];
        a[0]=n;
        for(i=0; i<SIZE; i++)
            printf("%d ",a[i]);
        return 0;
    }
    else if(n>a[SIZE-2])    //输入数n大于序列最大数则放a[SIZE-1]
    {
        a[SIZE-1]=n;
        for(i=0; i<SIZE; i++)
            printf("%d ",a[i]);
        return 0;
    }

    for(i=0; i<SIZE-1; i++)
    {
        if(n>=a[i]&&n<=a[i+1])
        {
            for(j=SIZE-1; j>i; j--)
                a[j]=a[j-1];
            a[i+1]=n;
            for(i=0; i<SIZE; i++)
                printf("%d ",a[i]);
            break;
        }
    }
    */

    //方案二
    for(i=SIZE-2;i>=0&&a[i]>n;i--)  //后入,把大的往后挪一个位置
        a[i+1]=a[i];
    a[i+1]=n;   //注意循环结束时i多减了一次
    for(i=0;i<SIZE;i++)
        printf("%d ",a[i]);
    return 0;
}

执行结果
在这里插入图片描述

小结

特殊情况是需要考虑,但不能一开始就从特殊情况开始写(比如方案一直接就开始从范围两边开始写),思路应是先着手写普遍(方案二),写好后再酌情是否添加特殊情况。
要注意先整体后局部的思维,不要从小处着眼顺着去推导全局!

NO.4 工资的排序

从文件salary.txt中读入工人的工资(不超过500人),全部增加20%(好事),然后对工资数据进行排序,将排序后的结果保存到文件ordered_salary.txt中。

#include <stdio.h>
#include<stdlib.h>
int main( )
{
    int n=0;
    double sala[500]= {0};
    FILE *fp,*fp1;

    if((fp=fopen("salary.txt","r"))==NULL)
    {
        printf("Can not open!\n");
        exit(1);
    }
    if((fp1=fopen("ordered_salary.txt","w"))==NULL)
    {
        printf("Can not open!\n");
        exit(1);
    }
    n=0;
    while((fscanf(fp,"%lf",&sala[n]))!=EOF) //读取数据放到sala[]
    {
        sala[n]=sala[n]*1.2;
        n++;
    }       //循环完毕sala[n]==EOF(调试看到为零1.79e-307),说明只读取到n个数(sala[0]开始)
    fclose(fp);

    int i,j;
    double t;
    for(i=0; i<n-1; i++)
        for(j=0; j<n-i-1; j++)
        {
            if(sala[j]>sala[j+1])
            {
                t=sala[j];
                sala[j]=sala[j+1];
                sala[j+1]=t;
            }
        }
    for(i=0;i<n;i++)    //n个数据写入ordered_salary.txt
        fprintf(fp1,"%.2lf\n",sala[i]);
    fclose(fp1);
    return 0;
}

执行结果
在这里插入图片描述

小结

易错点:

  1. 文件指针错定义为int型
  2. 直接在原文件操作排序。用一个二元素数组a[2]直接循序渐进读取文件数据并排序,只遍历一次,而没有采取把数据写入到500元素数组,对数组元素冒泡排序
  3. 对文件操作不熟悉
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值