數據結構與算法分析 #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[]是存係數的數組

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章