算法分析与设计(第三周)【已完结】

本周知识要点:

3.1 C语言中的类型转换机制

3.2 整数次幂(高次数的快速计算)

3.3 筛选素数算法

 

 

1.C语言中的类型转换的简单介绍

1.1 (同为signed类型 或 unsigned类型)长整数转短整数

规则:丢掉高字节部分,只保留低位字节。长整数的值若在短整数的范围内,则转换结构保持不变。 

1.2  短整数转长整数

规则:如果短整数带符号,则长整数高字节bit填充符号;否则填0

        (unsigned的作用,仅在于赋更大的初值、转换时填充的符号位。)

1.3 小数转小数

规则:有效数字部分,保留高bit,丢掉低bit;指数部分,按整数形式转换。

1.4 整数转小数

规则:保留高位的bit作为有效数字,指数正常计算出多少位

1.5 小数转整数

规则:有效数字作为 long long型,按指数计算小数点位进行移动,这个过程会舍去小数或高位溢出部分(即:丢掉小数部分,对整数部分按整数转)

(最后其实都是看二进制的转换,以及这个类型给多少bit位置来进行保留)

 

 

 

2. 整数次幂问题 及其 算法设计与分析

问题描述:对于一个数进行n次方计算(不考虑数值溢出等问题),如果设计算法使得计算最快。

2.1 (最直观的算法)算法一:

思路:直接用n重循环进行 n次乘法可得

int way_one(int x, int n)
{
	int a = x;
	for (int i = 1;i < n;i++)a = a*x;
	return a;
}

易得 时间复杂度T\left ( n \right ) = O\left (n \right )

 

2.2  (递归)算法二:

思路:每一次得到x^{n},假如n是偶数则直接由x^{n/2}相乘可得,如果n是奇数则由 x^{\left ( n -1\right )/2}相乘 再乘x得。

最后递归的边界条件是 x一次方 返回自己。

int way_two(int a, int x, int n)
{
	if(n == 1) return x;
	else
	{			
		if(n%2 ==0)return way_two(a,x,(n/2))*way_two(a,x,(n/2));
		else return way_two(a,x,(n-1)/2)*way_two(a,x,(n-1)/2)*a;
	}

}

因为每一次递归都大约是计算的一半 所以T\left ( n \right ) = O\left ( log\left ( n \right ) \right )

 

2.3 (非递归)算法三:

思路:由递归算法可得到启发,把n次方写成二进制的形式就可以轻松得到是 一个简单的循环公式。如2的10次方可写成2的(2+8)次方,所以 我们只需要让 第1次循环 和第3次循环 相乘即可。

int way_three(int x,int n)
{
	int result = 1;	
	for(int i = 0;n!=0; n = n/2)
	{
		// 判断是否现在的二进制是否是1 
		if(n%2 == 1) result *=x;
		x =x*x;		
	}
	return result;
	
}

n次循环大约被分成很多个2,是计算的很多个一半, 所以T\left ( n \right ) = O\left ( log\left ( n \right ) \right )

 

2.4 (无法正确实现)算法四:

思路: 用尽量少的步骤得到目的数次方,得需要穷举搜索一遍得到路径 再由路径去得到次方数,穷举搜索就已经耗费很多计算量所以无法正确实现。(个人认为)

 

2.5 扩展,由乘法到加法,用最少的加法得到一个多项式的定值计算——秦九韶算法

秦九韶算法介绍:https://baike.baidu.com/item/%E7%A7%A6%E4%B9%9D%E9%9F%B6%E7%AE%97%E6%B3%95/449196?fr=aladdin

 

 

3. 筛素数问题 及其 算法设计与分析

问题描述

问题一:判断一个数n是否是素数

问题二:筛选正整数n之前的素数,并输出出来

问题一就不再多说,可以遍历\sqrt{n}之前去整除,应该是目前常用的算法,现在就问题二进行算法设计

 

3.1  算法一:

思路:用前面的素数 去筛去后面他的整数倍,比如在n个之中,从2开始 往后删,每遇到一个没被删的由此开始又继续想后删除

算法设计,两重循环,第一重遍历整个n,第二重如果遍历n的同时遇到未删除的情况就开始由此往后删除。

#include<stdio.h>

int main()
{ 
	int n = 1000; // 筛选n之前的素数 
	// 生成整数n之前的数组,作用是用来标记是否被筛走 
	int a[n+1];
	for(int i = 1;i<=1000;i++)a[i] = i;
	
	for(int i = 2; i <= n;i++)
	{
		if(a[i] != -1)
		{
			printf("%d\n",a[i]);
			for(int k = 2;k*i <= n;k++)
			{
				a[k*i] = -1;			
			}
		}		
	}
} 

算法分析,利用欧拉级数定理可求得。T\left ( n \right ) = O\left ( n*log\left ( log\left ( n \right ) \right ) \right ),参考维基百科:https://en.wikipedia.org/wiki/Proof_of_the_Euler_product_formula_for_the_Riemann_zeta_function

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值