大话理论-了解算法01

嵌入式开发,难免会碰到一些用C去实现一些算法,或者基于某个算法调整一些参数的工作内容。最近看了一本《算法图解》,一个讲算法入门的书,我本着将书读薄的理念,将此书的脉络摘出来,针对不同的问题,分了几个小短文分别叙述,力图能在你的脑中勾勒出一个算法的基本概念。

排序问题

将一组已知的数据集合按照某种规则完成从无序变为有序,这就是我们经常需要面临的排序问题。选择排序作为这种问题最简单的算法,比如有一个数组,其数据按照[6,2,5,1]排列,我们依次选择这个数组中最大的值,从原数组删除,然后存放到另一个数组中,那么我们就会得到一个降序的数组[6,5,2,1]。
在这里我们先简单的介绍两个概念。首先是能够表示算法速度的大O表示法。就选择排序这种算法,他的速度用大O表示法就是O(n2),这种表示法是表示集合的元素个数n和算法执行时间的关系。
举个例子,数组包含元素个数为1时,时间是0(1),数组包含元素个数为2时,时间是O(4),而O(4)/O(1)=4才是具有实际意义的(待排序集合为两个元素时算法消耗的时间是待排序集合元素为一个时的四倍)。
其次是递归,简而言之就是不断的更新输入参数调用自己,在每次调用的过程中判断输入的参数符合回退条件,符合则一层层回退并最终退出,不符合则执行递归条件。
我们理解递归,不如从函数执行的顺序倒过来思考这个问题。先从输入参数遇到回退条件的情况开始想起。举个例子,我们需要写一个阶乘函数fn(n),我们试图写一个递归函数来解决问题。首先思考回退条件,当n=1时,fn(1)<=1,函数不需要进行任何操作,直接返回输入值即可。第二步假设n=k时,函数返回值为n的阶乘,当输入k+1时,我们函数需要执行(k+1)*fn(k)即可返回k+1的阶乘。由数学归纳法可知,函数fn(n)在n为任意值时都可以满足返回的值为输入的阶乘。

int fn(int n)
{
    if (n <= 1) return 1;

    return (n * func(n-1));
}

下面这部分Python代码用了递归来实现快速排序来应对排序问题,其算法平均的时间为O(n*log2n)。

def QuickSort(array):
    if len(array) <2:
        return array
   else:
       Pivot=array[0]
       Min=[i for i in array[1:] if i<=Pivot]
       Max=[i for i in array[1:] if i>Pivot]
       return quicksort(Min) + [Pivot] + quicksort(Max)

print QuickSort([10,5,2,3])

函数功能为输入一个无序数组,输出一个有序的数组。1.函数当array<=1时,直接返回即为有序数组。2.假设函数QuickSort(k)返回的是有序数组,当输入QuickSort(k+1)时,设多余元素为r,则数组QuickSort(l)+r+QuickSort(m)为有序数组(l数组为k数组中比r小的数集合,m数组为k数组中比r大数集合)。3.则函数输入任意数组,将返回一个有序数组。
函数执行的时间与选取的Pivot这个值有莫大的关系,它关系到了整个调用调用栈的层数,如果选择的Pivot值一直都保持输入数组中的最小值的话,那么层数将会为n,那么这个算法的操作时间将会是O(n2),如果选取的值为数组不大不小的值,才会是最好的情况O(n*log2n),当n足够大的时候,这种最好的情况可以被接受为平均的情况。

分而治之

这是书中提到的一种解决问题的思路,其类似于我们递归函数的思想,首先想出在什么条件下问题是最好解决的,然后缩小问题规模,直至问题出现在我们当初找到的条件。举个例子,需要将一块长方形田分成数个正方形田,最大的正方向变长是多少?首先我们用最大的正方形去分割,剩下的长方形在用最大可用的正方形分割,直至最后不再有剩余的长方形,即找到了最长的正方形变长。

查找算法

首先,待查表应该是有序的,然后找到位于表中部的元素,与待查元素作比较,小于则继续查待查表左半部分的元素,大于则查待查表右半部分的元素。这个查询算法每次都能排除掉待查表中一半的元素,查询的时间是O(log2n
二叉查找树这种数据结构将节点的左叶子存放比节点大的值,右叶子存放比节点小的值。是二分查找实际实现待查数据的数据结构。
如果你对数据库或高级数据结构感兴趣,可以研究如下数据结构:B数,红黑树,堆,伸展树。

原创文章 21 获赞 29 访问量 2万+

猜你喜欢

转载自blog.csdn.net/geek_liyang/article/details/88977310