素数判断,冒泡排序,查找数字,递归

文章介绍了素数的定义及判断方法,包括优化后的循环检查和封装成函数。接着讲解了冒泡排序的原理和实现,以及如何将其封装为函数。此外,还讨论了线性查找和二分查找两种查找算法,强调了二分查找的效率优势。最后,通过递归实现了阶乘计算,并对比了递归与非递归解法在斐波那契数列问题上的应用。
摘要由CSDN通过智能技术生成

素数判断

什么是素数?——素数一般指质数。质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

如果我们想写一个素数,必定要用一个循环来进行检验,设有检验数n,那就要用i[1,n]来与其进行计算,但由于除了1和n本身,其他数都不行,所以i的范围应该是[2,n-1]

int main()
{
  int n;
  scanf("%d",&n);
  for(int i=2;i<n;i++)
  {
    if(n%i==0)//就说明能被1和n本身以外的数整除,就说明不是素数
    {
       printf("%d是素数",n);
    }
  } 
  return 0;
}

现在,我们来查找100-200之间的素数

int main()
{
    int i = 0;
    int count=0;
    for (i = 100; i <= 200; i++)
    {
        //判断i是否为素数
        for(int j=2;j<i;j++)
        {
           if(i%j==0)
           {
              printf("%d是素数\n",i);
           } 
        } 
    }   
    printf("%d", count);
    return 0;
}

如果想封装成函数怎么弄?——最好能进行一个返回值的利用,返回1就是素数,0就不是素数

然后将返回值拿到主函数里用条件语句进行判断

且有一个可以减少运行时间的方法——若一个数n为100,那么用检验数(100开方-10)便可以检验出来,故用sqrt开方来减少计算量

//判断是不是素数
int is_prime(int i)//本质上代替了flag的作用
{
    int j = 0;
    for (j = 2; j <= sqrt(i); j++)
    {
        if (i % j == 0)
        {
            return 0;
        }       
    }
    return 1;
}
int main()
{
    int i = 0;
    int count=0;
    for (i = 100; i <= 200; i++)
    {
        //判断i是否为素数
        if (1 == is_prime(i))
        {
            printf("%d", i);
            count++;
        }
    }
    printf("%d", count);
    return 0;
}

冒泡排序

简而言之就是,排序的时候相邻两个进行比较,重复进行,一步步会将大的往后放,小的往前放,这样就会实现升序的排序

先想好比较步骤的代码——先进行比较,第j个与第j+1进行比较,若arr[j]>arr[j+1],那么就进行交换——需要一个tmp来储存数字,若arr[j]<arr[j+1]呢?

那就直接跳到下一个数字,也就是用arr[j+1]与arr[j+2]比较,这个过程需要用循环来实现'

//冒泡排序的次数
    for (i = 0; i < sz - 1; i++)
    {
        //一趟冒泡的次数
        int j = 0;
        for (j = 0; j < sz-1-i; j++)//因为每次都会排出一个最小值,所以我们每排除一个,则比较的次数-1
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }

在用之前,也需要知道数组的长度。

故主函数为

int main()
{
    int arr[] = { 3,1,5,9,2,4,7,6,8,0 };
    //排序-升序
    //冒泡排序
    int sz = sizeof(arr) // sizeof(arr[0]);//读取长度
    bubble_sort(arr,sz);//数组长度需要在外边传入
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d", arr[i]);
    }
    return 0;
}

那么再将冒泡排序封装成一个函数

//冒泡排序,相邻两个进行比较
void bubble_sort(int *arr,int sz)
{
    int i = 0;
    //int sz = sizeof(arr) / sizeof(arr[0]);//sz必须在函数外部求的,再传入
    // 
    // 为什么在外部传参的时候,传进去的sz是10?
    // 因为传入数组名时,实则传入的是数组首元素地址,首元素地址即1个元素,故sz在里边求就是1
    
    //冒泡排序的次数
    for (i = 0; i < sz - 1; i++)
    {
        //一趟冒泡的次数
        int j = 0;
        for (j = 0; j < sz-1-i; j++)//因为每次都会排出一个最小值,所以我们每排除一个,则比较的次数-1
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

查找数字

    • (逐一查找)

本质就是用for循环的遍历算法一个一个比较过去

若找到则返回相应的值(数组的下标)

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

    int k = 7;
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    //strlen是字符串专用
    int flag = 0;
    for (i = 0; i < sz; i++)
    {
        if (k == arr[i])
        {
            flag = 1;//用于标记是否能找到
            printf("找到了,下标是:%d", i);
            break;
        }
    }
    if (flag == 0)
    {
        printf("找不到\n");
    }
    return 0;
}

但是这样子的查找会比较久,而且每个都要过一遍会使代码运行比较久

那有什么更方便的方法呢?

2.二分查找

二分查找的定义:

简而言之,就是定义左右的数字,然后找到中间数,接着再次缩小范围找中间数

可以类比为,猜数字的方法

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

    int k = 7;
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    int left = 0;
    int right = sz - 1;//元素个数减去1就是最后一个元素对应的数组下标

    int flag = 0;//作为是否找到的标记
    while (left<=right)
    {
        //1.int mid = (left + right) / 2;//若这两个数太大,则会越界,导致一些数的丢失
        int mid = left + (right - left) / 2;//使两侧补齐,得到平均数
        if (arr[mid] < k)
        {
            left = mid + 1;//数字为小于要查找的数字时,说明要查找的数字在右边,故加1
        }
        else if (arr[mid] > k)//数字为大于要查找的数字时,说明要查找的数字在左边,故减1
        {
            right = mid - 1;
        }
        else
        {
            printf("找到了,下标是:%d\n", mid);
            flag = 1;
            break;
        }
    }
    if (flag == 0)
    {
        printf("没找到");
    }
    return 0;
}

举一个例子

递归

什么是递归?

递归的条件

  • 存在限制条件,当满足这个限制条件的时候,递归便不再继续。

  • 每次递归调用之后越来越接近这个限制条件。

阶乘

非递归,用简单的循环

int fac(int n)
{
    int i = 0;
    int ret = 1;
    for (i = 1; i <= n; i++)//一个一个乘过去
    {
        ret = ret * i;
    }
    return ret;
}

用递归,当要求的数>=1的时候就进入下一个递归

int fac(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else return n * fac(n - 1);
}
int main()
{
    int x;
    scanf("%d", &x);
    int ret=fac(x);
    printf("%d", ret);
    return 0;
}

递归的运用,需要萌新们多次的推算,多次画出流程图,才能很好地使用

斐波那契数列

斐波那契数列:

int Fib(int n)
{
    if (n <= 2)
        return 1;
    else
        return Fib(n - 1) + Fib(n - 2);
}

但是,这样子会使代码量及其巨大,在到一定数后,就会超出栈区

因此可以改为:(非递归)

int Fib(int n)
{
    int a = 1;
    int b = 1;
    int c = 1;
    while (n>=3)
    {
        c = a + b;
        a = b;
        b = c;
        n--;
    }
}

因此,递归和循环需要按照实际情况来判断,按照最简单的方式来求

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nick-An

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值