算法(一):阶乘、斐波那契、子集树、排列树

一、在c、linux下用指令规定栈的大小

  对于 x86 和 x64 计算机,默认堆栈大小为 1 MB。在 Itanium 芯片组上,默认大小为 4 MB。linux下默认的堆栈空间大小是8M或10M,不同的发行版本可能不太一样。可以使用ulimit指令查看栈空间大小,指令ulimit -s或者ulimit -a如下图:对于 x86 和 x64 计算机,默认堆栈大小为 1 MB。在 Itanium 芯片组上,默认大小为 4 MB。linux下默认的堆栈空间大小是8M或10M,不同的发行版本可能不太一样。可以使用ulimit指令查看栈空间大小,指令ulimit -s或者ulimit -a如下图:详细见原文:https://blog.csdn.net/liyuanyes/article/details/44097731

在这里插入图片描述

1.使用ulimit -s直接显示出栈空间大小10240,ulimit -a显示所有参数,其中stack size值是10240,表示栈空间大小是10M。注意:这里的单位是KB。我们也可以使用“ulimit -s 数字”来修改栈的大小,如下图将栈空间修改成8M:
在这里插入图片描述

  1. gcc 、g++编译时指定参数来规定栈的大小:
g++ filename.cpp -o hh -g -WL -stack=16777216(字节)
`$     ulimit -a | grep stack
stack size (kbytes,-s) 8192

二、阶乘

int fac(int n)         //递归求解    O(n)   S(n)
{
	if(n <= 1)
		return 1;
	else 
		return fac(n-1) * n;    //fac(n-1)指的是前n-1项的阶乘
}

int fun(int n)      //非递归求解(循环)  O(n)  S(1)
{
	int sum = 1;
	for(int i = 1;i<=n;++i)
	{
		sum = sum * i;
		if(sum < 0) return -1;     /*  存在问题:所得结果可能超出int 型的取值范围,发生栈溢出 ,输出一个负数*/
	}
	return sum;
}

int main()
{
	int n = 4;
	int sum = fac(n);
	return 0;
}

二、斐波那契数列两种方法及优化

int fac(int n)       //    斐波那契数列  递归      O(2^n)  s(n)
{
	if(n <= 2) 
		return 1;
	else 
		return fac(n-1)+fac(n-2);
}

int fun(int n)      // 斐波那契数列非递归循环求解   O(n) S(1)
{
	int a = 1, b = 1, c = 1;
	for(int i = 3;i<=n;++i)
	{
		c = a + b;
		b = a;
		a = c;
	}
	return c;
}

int main()
{
	int n = 10;
	int sum = 0;
	return 0;
}

在斐波那契数列计算中,用递归解法时间复杂度为O(2^n),时间复杂度太高,因此,提出了 O(2^n) ----->O(n) 的优化,如下:

int fac(int n,int a,int b)
{
	if(n <= 2) return a;
	else return fac(n-1,a+b,a);
}
int Fac(int n)
{
	int a = 1, b = 1;
	return fac(n,a,b);
}

三、排列树

在这里插入图片描述 首先,这是一个全排列问题,我们首先根据题意,可以画出排列树:
在这里插入图片描述思路:在序列R={1,2,3}中,当R减去1的时候,分别将(1,1)、(1,2)、(1,3)互换。每次互换时,k上移一层,继续将剩下的数字进行同样方法排列组合,直到组合只剩下一个元素就不需要排列,直接打印。

void Perm(int *ar,int k,int m)
{
	if(k == m)
	{
		for(int i = 0;i<=m;++i)
		{
			cout<<ar[i]<<" ";
		}
		cout<<endl;
	}
	else
	{
		for(int j = k; j<=m;++j)
		{
			swap(ar[j],ar[k]);
			Perm(ar,k+1,m);
			swap(ar[j],ar[k]);
		}
	}
}


int main()
{
	int ar[]={1,2,3};
	int n = sizeof(ar)/sizeof(ar[0]);
	Perm(ar,0,n-1);
	return 0;
}

四、子集树

题目:对于集合R={1,2,3},打印出他所有的子集,包括空集。

{1,2,3}
{1,2} {1,3} {2,3}
{1} {2} {3}
{}
首先我们根据题意,可以构造出一颗子集树:
在这里插入图片描述此树,左子树全为1,右子树全为0。构建代码如下:

void fun(int *ar,int *br,int i,int n)
{
	if(i>=n)
	{
		for(int j = 0;j<n;++j)
		{
			if(br[j])
			{
				cout<<ar[j]<<" ";
			}
		}
		cout<<endl;
	}
	else
	{
		br[i] = 1;
		fun(ar,br,i+1,n); // left       (i+1,n)
		br[i] = 0;
		fun(ar,br,i+1,n); // right;     (i+1,n)
	}
}


int main()
{
	int ar[]={1,2,3};
	int br[]={0,0,0};
	fun(ar,br,0,3);

	return 0;
}

在这里插入图片描述

五、根据代码构建树

void fun(int i,int n)
{
	if(i>=n)
	{
		cout<<i<<endl;
	}
	else
	{
		fun(i++,n);
		fun(i++,n);
	}
}
int main()
{
	int i = 0, n = 3;
	fun(i,n);
	return 0;
}

在这里插入图片描述
结果:0-0-0死循环
2.

void fun(int &i,int n)
{
	if(i>=n)
	{
		cout<<i<<endl;
	}
	else
	{
		fun(++i,n);
		fun(++i,n);
	}
}
int main()
{
	int i = 0, n = 3;
	fun(i,n);
	cout<<i<<endl;
	return 0;
}

在这里插入图片描述结果:3,4,5,6

void fun(int &i,int n)
{
	if(i>=n)
	{
		cout<<i<<endl;
	}
	else
	{
		fun(i+1,n);
		fun(i+1,n);
	}
}
int main()
{
	int i = 0, n = 3;
	fun(i,n);
	cout<<i<<endl;
	return 0;
}

在这里插入图片描述
4.

void fun(int &i,int n)
{
	if(i>=n)
	{
		cout<<i<<endl;
	}
	else
	{
		fun(i++,n);
		fun(i++,n);
	}
}
int main()
{
	int i = 0, n = 3;
	fun(i,n);
	cout<<i<<endl;
	return 0;
}

i++存放临时量,具有常性,不能引用。

六、二分查找法

  1. 非递归方法
template<class Type>
int Search(const Type *ar,int left,int right , const Type &kx)
{
	int pos = -1;
	if(left <= right)
	{
		int mid = (right - left + 1)/2 + left;
		if(kx < ar[mid])
		{
			pos = Search(ar,left,mid-1,kx);
		}else if(kx > ar[mid])
		{
			pos = Search(ar,mid+1,right,kx);
		}else
		{
			while(mid > left && ar[mid-1] == kx) --mid;
			pos = mid;
			break;
		}
	}
	return pos;
}

template<class Type>
int SearchValue(const Type *ar,int n , const Type &kx)        //递归方法
{
	if(NULL == ar || n < 1) return -1;
	else 
		return Search(ar,0,n-1,kx);
}

template<class Type>
int FindValue(const Type *ar,int n ,const Type &kx)     //非递归
{
	int pos = -1;
	if(NULL == ar || n < 1) return pos;
	int left = 0 , right = n - 1;
	while(left <= right) // < <=
	{
		int mid = (right - left + 1)/2 + left;// (right + left)/2
		if(kx < ar[mid])
		{
			right = mid - 1;
		}else if(kx > ar[mid])
		{
			left = mid + 1;
		}else
		{
			while(mid > left && ar[mid-1] == x) --mid;
			pos = mid;
			break;
		}
	}
	return pos;
}

int main()
{
	int ar[]={12,23,34,45,45,45,45,45,56,67,78,89,90,100};
	int n = sizeof(ar)/sizeof(ar[0]);
	int x = 56;
	int pos = FindValue(ar,n,x);
	pos = SearchValue(ar,n,x);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值