数据结构与算法分析 #2.7 随机置换 #2.9求幂的算法&horner法则(即秦九昭算法)

·问题描述

假设需要生成前N个自然数的一个随机置换。例如,{4,3,1,5,2}和{3,1,4,2,5}就是合法的置换,但{5,4,1,2,1}却不是,因为数1出现两次而数3却没有。这个程序常常用于模拟一些算法。我们假设存在一个随机数生成器RandInt(i,j),它以相同的概率生成i和j之间的一个整数。

//生成前N个自然数的一个随机置换。比较下列三种算法的效率
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define CONTAINER 2000000
//#define DEBUG 1

int RandInt(int leftborder, int rightborder);//产生随机数x,leftborder<=x<=rightborder

void Algorithm_pow_N_1(int array[], int n);//第一个算法,运行时间=O(N²logN), 传入数组、数组长度
void Algorithm_pow_N_2(int array[], int n);//第二个算法,运行时间=O(NlogN), 传入数组、数组长度

void Algorithm_pow_N_3(int array[], int n);//第三个算法,运行时间=O(N), 传入数组、数组长度    思路神奇好好学习

int main()
{
		clock_t starttime, endtime;
		int array[CONTAINER];
		srand(time_t(NULL));

		starttime = clock();
		Algorithm_pow_N_3(array, CONTAINER);
		endtime = clock();
		printf("——total running time: %lf s\n",(double)(endtime - starttime) / CLOCKS_PER_SEC);
	system("pause");
	return 0;
}

//产生随机数x,leftborder<=x<=rightborder
int RandInt(int leftborder, int rightborder)
{
	return rand() % (rightborder - leftborder + 1) + leftborder;
}

//第一个算法,运行时间=OO(N²logN), 传入数组、数组长度
//每次生成随机数都遍历已添入的数据确保不重复
void Algorithm_pow_N_1(int array[], int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		int insert;
		do
		{
			insert = 0;
			array[i] = RandInt(1, n);
			for (j = 0; j < i; j++)
			{
				if (array[i] == array[j])
				{
					insert = 1;
					break;
				}
			}
		} while (insert);
		
#ifdef DEBUG
		printf("test:array[%d]= %d\n", i, array[i]);
#endif // DEBUG

	}
}

//第二个算法,运行时间=O(NlogN), 传入数组、数组长度
//插旗,给每个已经读入的数据立flag代表使用过
void Algorithm_pow_N_2(int array[], int n)
{
	int used[CONTAINER+1] = { 0 };
	for (int i = 0; i < n; i++)
	{
		int ran;
		do
		{
			ran = RandInt(1, n);
		} while (used[ran]);
		array[i] = ran;
		used[ran] = 1;
		#ifdef DEBUG
		printf("test:array[%d]= %d\n", i, array[i]);
		#endif // DEBUG
	}
}


//第三个算法,运行时间=O(N), 传入数组、数组长度    思路神奇好好学习
void Algorithm_pow_N_3(int array[], int n)
{
	int i;
	for (i = 0; i < n; i++)
		array[i] = i + 1;
	for (i = 0; i < n; i++)
	{
		int ran = RandInt(0, n - 1);
		int swap;
		swap = array[ran];
		array[ran] = array[i];
		array[i] = swap;
#ifdef DEBUG
		printf("test:array[%d]= %d\n", i, array[i]);
#endif // DEBUG
	}
}

·问题描述:计算F(X)=nΣi=0 x^i 用基础程序和递归程序执行,比较运算时间

//计算F(X)=nΣi=0 x^i 用基础程序和递归程序执行,比较运算时间
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

int simplypower(int x, int n);//求x的n次幂  O(N^2)
int recursionpower(int x, int n);//分治递归版 O(NlogN)

int main()
{
	int x, n;
	long int sum = 0;
	int i;
	clock_t start, end;

	printf("please enter a number and the power you want to calculate\n");
	scanf("%d%d", &x, &n);
	start = clock();
	for (i = 0; i <= n; i++)
		sum += recursionpower(x, i);
	printf("F(X)=nΣi=0 x^i=  %d\n", sum);
	end = clock();

	printf("total calulating time: %lf   s\n", (end - start) / CLOCKS_PER_SEC);

	system("pause");
	return 0;
}

int simplypower(int x, int n)//求x的n次幂
{
	long int result = 1;
	int i = 0;
	for (i; i < n; i++)
		result *= x;
	return result;
}

int recursionpower(int x, int n)//分治递归版
{
	if (n == 1)
		return x;
	else if (!n)
		return 1;
	else
	{
		if (n % 2)//n为奇数
		{
			return recursionpower(x, (n - 1) / 2)*recursionpower(x, (n - 1) / 2)*x;
		}
		else
			return recursionpower(x, n / 2)*recursionpower(x, n/ 2);
	}
}
仍存问题:c中大数的存储——数组或链表字符串的方式存储(未在本函数中尝试实现,待研究)

故本函数对大数处理无力,超出long int数据长度

Horner法则

多项式求值问题,最容易想到的算法是求出每一项的值然后所求值累加起来,这种算法的时间和空间效率都不高,对于数据规模不大的题目来说由于其直观、简单很容易被大家采纳,可一旦数据规模过大时,这种算法就显得无能为力了,下面介绍一种解决这类求值问题的高效算法――霍纳法则。在中国,霍纳法则也被称为秦九韶算法。

思路:不断提出底数x。
例如,当x=3时,计算p(x)=2x^4-x^3+3x^2+x-5的值。对于多项式p(x)=2x^4-x^3+3x^2+x-5,我们按霍纳法则进行变换,有:
p(x)=2x^4-x^3+3x^2+x-5
=x(2x^3-x^2+3x+1)-5
=x(x(2x^2-x+3)+1)-5
=x(x(x(2x-1)+3)+1)-5
代码实现:
poly=0;
for(int i=n;i>=0;i--)
poly=x*poly+A[i];//A[]是存系数的数组

猜你喜欢

转载自blog.csdn.net/weixin_40505645/article/details/79941860