「データ構造コンピュータ実験(C言語実装)」ノート(1/12):はじめに

確認実験

1からnまでの連続する整数の合計を求めます

説明する

与えられた正の整数nについて、1 +2+…+n1 + 2+…+nを見つけます1+2++n、累積合計を使用n(n + 1)2 \ frac {n(n + 1)} 22n n 1(ガウスの方法)2つの解決策。

同じnについて、これら2つの解の合計結果と解時間が与えられ、関連するデータでテストされます。

  • clock_tタイプ、clock()関数、およびCLOCKS_PER_SEC定数は、time.hヘッダーファイルで宣言されています。
  • clock_tは、クロックデータ型(long)です。
  • 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⁡2n\log_2nと入力します。lo g2n n\ sqrt nn nnnnlog⁡2nn \ log_2nnlo g2nn 2 n ^ 2n2n 3 n ^ 3n3、2 n2 ^ n2nn!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について、2つのソリューションの結果とソリューション時間が与えられ、関連するデータでテストされます。

グレーディング

//文件名: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