《数据结构上机实验(C语言实现)》笔记(1 / 12):绪论

验证性实验

求1~n的连续整数和

说明

对于给定的正整数n,求 1 + 2 + … + n 1+2+…+n 1+2++n,采用逐个累加和 n ( n + 1 ) 2 \frac {n(n+1)} 2 2n(n1)(高斯法)两种解法。

对于相同的n,给出这两种解法的求和结果和求解时间,并用相关数据进行测试。

  • clock_t类型、clock()函数和CLOCKS_PER_SEC常量均在time.h头文件中声明。
  • clock_t是时钟数据类型(长整型数)
  • clock()函数返回CPU时钟计时单元数(以毫秒为单位)
  • CLOCKSPER_SEC是一个常量,表示1秒包含的毫秒数。
  • 表达式((float) t)/CLOCKS_PER_SEC返回t转换成的秒数;

放码

//文件名:exp1-1.cpp

//求1+2+...+n
#include <stdio.h>
#include <time.h>       // clock_t, clock, CLOCKS_PER_SEC
#include <math.h>

//方法1:老实累加
long add1(long n)     
{
    
    
	long i, sum = 0;
	for (i = 1; i <= n; i++)
		sum += i;
	return(sum);
}


void AddTime1(long n)  /* 采用方法1的耗时统计 */
{
    
    
	clock_t t = clock();
	long sum = add1(n);
	t = clock() - t;
	printf("方法1:\n");
	printf("  结果:1~%d之和:%ld\n", n, sum);
	printf("  用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}


//方法2:用公式
long add2(long n)     /* 方法2:求1+2+...+n */
{
    
    
	return(n * (n + 1) / 2);
}


void AddTime2(long n) /* 采用方法2的耗时统计 */
{
    
    
	clock_t t = clock();
	long sum = add2(n);
	t = clock() - t;
	printf("方法2:\n");
	printf("  结果:1~%d之和:%ld\n", n, sum);
	printf("  用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}

int main()
{
    
    
	int n;
	printf("n(大于1000000):");
	scanf("%d", &n);
	if (n < 1000000)
		return(0);
	AddTime1(n);
	AddTime2(n);
	return(1);
}

结果

n(大于1000000):99999999
方法1:
  结果:1~99999999之和:887459712
  用时:0.222000秒
方法2:
  结果:1~99999999之和:887459712
  用时:0.000000秒
请按任意键继续. . .

常见算法时间函数的增长趋势分析

说明

理解常见算法时间函数的增长情况。

对于1~n的每个整数n,输 log ⁡ 2 n \log_2n log2n n \sqrt n n n n n n log ⁡ 2 n n \log_2n nlog2n n 2 n^2 n2 n 3 n^3 n3 2 n 2^n 2n n ! n! n!

放码

//文件名:exp1-2.cpp
#include <stdio.h>
#include <math.h>

double log2(double x)	//求log2(x)
{
    
    
	return log10(x)/log10((double)2);
}

long exponent(int n)	//求2^n
{
    
    
	long s=1;
	for (int i=1;i<=n;i++)
		s*=2;
	return s;
}

long factorial(int n)	//求n!
{
    
    
	long s=1;
	for (int i=1;i<=n;i++)
		s*=i;
	return s;
}

void fun(int n)
{
    
    
	printf("log2(n) sqrt(n)  n       nlog2(n)   n^2	    n^3	     2^n		n!\n");
	printf("===========================================================================\n");
	for (int i=1;i<=n;i++)
	{
    
    
		printf("%5.2f\t",log2(double(i)));
		printf("%5.2f\t",sqrt((double)i));
		printf("%2d\t",i);
		printf("%7.2f\t",i*log2(double(i)));
		printf("%5d\t",i*i);
		printf("%7d\t",i*i*i);
		printf("%8d\t",exponent(i));
		printf("%10d\n",factorial(i));
	}
}

int main()
{
    
    
	int n=10;
	fun(n);
	return 1;
}

结果

log2(n) sqrt(n)  n       nlog2(n)   n^2     n^3      2^n                n!
===========================================================================
 0.00    1.00    1         0.00     1         1        2                 1
 1.00    1.41    2         2.00     4         8        4                 2
 1.58    1.73    3         4.75     9        27        8                 6
 2.00    2.00    4         8.00    16        64       16                24
 2.32    2.24    5        11.61    25       125       32               120
 2.58    2.45    6        15.51    36       216       64               720
 2.81    2.65    7        19.65    49       343      128              5040
 3.00    2.83    8        24.00    64       512      256             40320
 3.17    3.00    9        28.53    81       729      512            362880
 3.32    3.16   10        33.22   100      1000     1024           3628800
请按任意键继续. . .

设计性实验

求素数个数

说明

通过对比同一问题不同解法的绝对执行时间 ,体会如何设计“好”的算法。

求1~n的素数个数。对于相同的n,给出这两种解法的结果和求解时间,并用相关数据进行测试。

放码

//文件名:exp1-3.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>		 	//clock_t, clock, CLOCKS_PER_SEC
#include <math.h>

//------方法1-----------------------------------------------
bool prime1(long n) //方法1:判断正整数n是否为素数
{
    
    
	long i;
	for (i = 2; i < n; i++)
	if (n % i == 0)
		return false; //若n不是素数,则退出并返回false
	return true;
}

void PrimeTime1(long n) //采用方法1的耗时统计
{
    
    
	long sum = 0, i;
	clock_t t = clock();
	for (i = 2; i <= n; i++)
		if (prime1(i))
			sum++;
	t = clock() - t;
	printf("方法1:\n");
	printf("  结果:2~%d的素数个数:%d\n", n, sum);
	printf("  用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}


//------方法2-----------------------------------------------
bool prime2(long n) //方法2:判断正整数n是否为素数
{
    
    
	long i;
	for (i = 2; i <= (int)sqrt((double)n); i++)//对n开方进行优化
	if (n % i == 0)
		return false; //若n不是素数,则退出并返回false
	return true;
}
void PrimeTime2(long n) //采用方法2的耗时统计
{
    
    
	long sum = 0, i;
	clock_t t = clock();
	for (i = 2; i <= n; i++)
		if (prime2(i))
			sum++;
	t = clock() - t;
	printf("方法2:\n");
	printf("  结果:2~%d的素数个数:%d\n", n, sum);
	printf("  用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}


//------方法3-----------------------------------------------
int countPrimes(long n) //方法3:埃拉托色尼筛选法,空间换时间,n不能过大,否则程序报错
{
    
    
	bool *flag = (bool *)malloc(n * sizeof(bool));
	for (long i = 0; i < n; i++)//这步不能省略,否则得不到正确值
		flag[i] = 0;

	int count = 0;
	for (long i = 2; i < n; i++){
    
    
		if (flag[i] == 0){
    
    
			count++;
			for (long j = i; i * j < n; j++) {
    
    
				flag[i * j] = 1;
			}
		}
	}
	free(flag);
	return count;
}
void PrimeTime3(long n) //采用方法3的耗时统计
{
    
    
	long sum = 0;
	clock_t t = clock();
	sum = countPrimes(n);
	t = clock() - t;
	printf("方法3:\n");
	printf("  结果:2~%d的素数个数:%d\n", n, sum);
	printf("  用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}

//------------------------------------------------------------
int main() {
    
    
	long n;
	printf("n(取值范围[10000, 40000]):");
	scanf("%d", &n);
	if (!(10000 <= n && n <= 40000)) return 0;
	PrimeTime1(n);
	PrimeTime2(n);
	PrimeTime3(n);
	return 1;
}

结果

n(取值范围[10000, 40000]):40000
方法1:
  结果:2~40000的素数个数:4203
  用时:0.236000秒
方法2:
  结果:2~40000的素数个数:4203
  用时:0.009000秒
方法3:
  结果:2~40000的素数个数:4203
  用时:0.001000秒
请按任意键继续. . .

求连续整数阶乘的和

说明

对于给定的正整数n,求1!+2!+3!+…+n !。给出一种时间复杂度为O(n)的解法。

放码

//文件名:exp1-4.cpp
#include <stdio.h>

//循环版
long Sum(int n) {
    
    
	long sum = 0, fact = 1;
	for (int i = 1; i <= n; i++) {
    
    
		fact *= i;
		sum += fact;
	}
	return sum;
}

//TODO:递归版

//------------------------------------------------------------
int main() {
    
    
	int n;
	printf("n(3-20):");
	scanf("%d", &n);
	if (n < 3 || n > 20) return 0;
	printf("1!+2!+…+%d!=%ld\n", n, Sum(n));
	return 1;
}

结果

n(3-20):15
1!+2!+…+15!=1443297817
请按任意键继续. . .

猜你喜欢

转载自blog.csdn.net/u011863024/article/details/122048972