一日一文(1)

听说了很多的大牛的成长历程都从写自己的博客开始

虽然很久之前就开了博客但是没有坚持下去,从今天开始让自己养成这样的习惯。学着写博客、学着分享。

每天尽量发一篇文章、其他学习文章随着学习进度慢慢写

第一天学习计划:学习算法递归与分支策略,写出二分搜索算法、合并排序算法、快速排序算法

0X00 递归思想:

1、相关概念

直接调用自己或者间接通过一些语句调用自己

一个使用函数自身给出定义的函数叫做递归函数

        优点:描述问题自然,证明算法容易

        缺点:时间、空间复杂度高

一个递归问题可以分为“回推”和“逆推”两个阶段

2、递归应满足的条件

定义中必须包含一个基本部分,其中对于n的一个或多个值,f(n)必须是直接定义的(也就是必须有递归的出口)

在递归部分中,右侧出现的所有f的参数必须有一个比n小(保证每次递归调用规模减小)

3、经典例题

~Fibonacci数列递归算法

int Fibonacci(int n)
{
	if(n <= 1)  
		return 1;
	return Fibonacci(n - 1) + Fibonacci(n - 2);
}
~排列问题的递归算法

/*
*问题描述
*设计一个递归算法生成n个元素{r1,r2,……,rn}的全排列。记为perm({r1,r2,……,rn}).
*解决思路
*设R={r1,r2,……,rn}是要进行排列的n个元素,Ri=R-{ri}。
*/

template<class T>
void Perm(T list[], int k, int m) //生成所有[k:m]的排列方式
{
	int i;
	if(k == m)   //递归出口
	{
		for(i=0; i <= m; i++)
			cout << list[i];
		cout << endl;
	}
	else  //递归产生各种排列
	{
		for(i = k; i <= m; i++)
		{  //i=>ri
			swap(list[i],list[k]);  
			Perm(list, k+1, m);		//对n-1个元素进行全排列
			swap(list[i],list[k]);	//排列后为保证无重复结果,将ri换回
		}
	}
}
0X01 分治法思想

1、基本概念

分治法解决一个大的问题时可以分成多个更小的问题、分别解决每个小问题后将每个小问题的解答组合起来,得到原来大问题的解

分治思想解决问题的代码模型为:

Divide-and-Conquer(P)   //P为求解问题的规模
{
	if(|P| <= n0) Adhoc(P);  //判断规模P是否足够小,即子问题的规模
	divide P into smaller subinstances P1,P2,…,Pk;
	for(i=1;i<=k;i++)
		yi=Divide-and-Conquer(Pi);  //分治解决问题
	return Merge(y1,…,yk);  //合并子问题结果得到最终结果
}

2、经典问题

~二分搜索

/*
*问题描述
*给定已排好序的n个元素,在n个元素中找出一特定元素x,找到则将其位置交给赋值给变量j,否则j=-1
*解决思想
*取中间元素作比较元素,相等则返回,不相等则在相应的位置继续寻找
*/


template<class T>
int binarySearch(T list[], const T& x, int n)	//list为排好顺序的数组、x为寻找的元素、n为数组规模
{
	int left = 0, right = n-1;
	int middle = 0;
	while(left <= right)
	{
		middle = (left + right) / 2;
		if(list[middle] == x) return middle;
		if(x > list[middle]) left = middle + 1;
		else right = middle - 1;
	}
	return -1;
}

~合并排序——插入法

/*
*问题描述
*已知n个元素的数组list[1:n],将list中元素按不降序排列
*解决思路
*从第二个元素开始取出与之前的第i个元素进行大小对比
*当遇到不小于list[i]的元素时插入list数组
*/

template<class T>
void insertionSort(T list[], int n)	//数组list、数组规模n
{
	T item;
	int i;
	for (int j = 1; j < n; j++)
	{
		item = list[j];        //取出当前元素
		i = j - 1;
		while (item < list[i] && i>-1)
		{
			list[i + 1] = list[i];
			i--;
		}
		list[i + 1] = item;
	}
}
算法时间复杂度分析:插入算法的while循环中语句执行次数可能为0~j次,因此最坏的时间复杂度为O(n^2),当然,输入之前就是排好顺序的话时间复杂度为最好情况的O(n)

~2、归并排序

void merge(int *data, int start, int end, int *result)
{
	int left_length = (end - start + 1) / 2 + 1;//左部分区间的数据元素的个数
	int left_index = start;
	int right_index = start + left_length;
	int result_index = start;
	while (left_index < start + left_length && right_index < end + 1)
	{
		//对分别已经排好序的左区间和右区间进行合并
		if (data[left_index] <= data[right_index])
			result[result_index++] = data[left_index++];
		else
			result[result_index++] = data[right_index++];
	}
	while (left_index < start + left_length)
		result[result_index++] = data[left_index++];
	while (right_index < end + 1)
		result[result_index++] = data[right_index++];
}
void merge_sort(int *data, int start, int end, int *result)
{
	if (1 == end - start)//如果区间中只有两个元素,则对这两个元素进行排序
	{
		if (data[start] > data[end])
		{
			int temp = data[start];
			data[start] = data[end];
			data[end] = temp;
		}
		return;
	}
	else if (0 == end - start)//如果只有一个元素,则不用排序
		return;
	else
	{
		//继续划分子区间,分别对左右子区间进行排序
		merge_sort(data, start, (end - start + 1) / 2 + start, result);
		merge_sort(data, (end - start + 1) / 2 + start + 1, end, result);
		//开始归并已经排好序的start到end之间的数据
		merge(data, start, end, result);
		//把排序后的区间数据复制到原始数据中去
		for (int i = start; i <= end; ++i)
			data[i] = result[i];
	}
}
~快速排序

void sort(int array[], int left, int right) {
	int ltemp = left, rtemp = right;
	int f = array[(left + right) / 2];
	while (ltemp<rtemp)
	{
		while (array[ltemp] < f)
		{
			ltemp++;
		}
		while (array[rtemp] > f)
		{
			rtemp--;
		}
		if (ltemp < rtemp) {
			int temp = array[ltemp];
			array[ltemp] = array[rtemp];
			array[rtemp] = temp;
			ltemp++;
			rtemp--;
		}
	}
	if (ltemp == rtemp) {
		ltemp++;
	}
	if (left < rtemp) {
		sort(array, left, ltemp - 1);
	}
	if (ltemp < right) {
		sort(array, rtemp + 1, right);
	}
}
好的问题大概就这样,明天计划学一下python的正则表达式、多线程以及一些其他的算法。

希望自己能坚持下去。













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值