《算法精解 C语言描述》

算法设计的一般方法

随机法依赖于随机数的统计特性。一个应用随机法的例子是快速排序。

分治法

动态规划

贪心法

近似法——旅行商问题

指针

在C语言中,通常声明一个void指针来表示泛型指针。

对于泛型指针来说类型转换非常重要,因为只有告诉泛型指针通过何种类型来访问地址时,泛型指针才能正确取到值。这是由于泛型指针不会告诉编译器它指向的是何种类型数据,因此编译器不知道多少个字节要被访问。也不知道应该如何解析字节。

函数指针是指向可执行代码段或调用可执行代码段的信息块的指针。

例如,在下面一段代码中,match被声明为一个函数指针,它接受两个void指针类型的参数,同时返回一个整型。

  1. int(*match)(void*key1,void*key2);

假设有一个match_int函数,它的两个void 指针参数指向整型并回返1。可以这样赋值:

  1. match = match_int;

调用:

  1. retval = match(&x,&y);

递归

当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分,这个递归调用就是尾递归。

当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活跃记录而不是在栈中去创建一个新的。

示例:以尾递归的形式计算阶乘的一个函数实现

  1. //facttail.c
  2. #include"facttail.h"
  3. int facttail(int n,int a)
  4. {
  5. if(n <0)
  6. return0;
  7. elseif(0== n)
  8. return1;
  9. elseif(1== n)
  10. return a;
  11. else
  12. return facttail( n -1, n * a);
  13. }

计算n!:

  1. facttail(n,1);

哈希表

示例:一个适用于处理字符串的哈希函数

  1. //hashpjw.c
  2. #include"hashpjw.h"
  3. //hashpjw
  4. unsignedint hashpjw(constvoid*key)
  5. {
  6. constchar*ptr;
  7. unsignedint val;
  8. //hash the key by performing a number of bit operations on it
  9. val =0;
  10. ptr = key;
  11. while(*ptr !=‘\0‘)
  12. {
  13. unsignedint tmp;
  14. val =(val <<4)+(*ptr);
  15. if( tmp =(val &0xf0000000))
  16. {
  17. val = val ^(tmp >>24);
  18. val = val ^ tmp;
  19. }
  20. ptr++;
  21. }
  22. //In practice, replace PRIME_TBLSIZ with the actual table size.
  23. return val % PRIME_TBLSIZ;
  24. }

树的平衡

树的平衡是指对于给定数量的结点,保证树的高度尽可能短的过程。这意味着在结点加入下一层之前必须保证本层结点满额。正式的说法是,如果满足树的所有叶子结点都在同一层上,或者所有 叶子结点都在最后两层上,且倒数第二层是满的,则这棵树是平衡的。

如果一棵平衡树最后一层的所有叶子结点都在最靠左边的位置上,则称这棵树是左平衡的。

表达式树


针对表达式(((74-10)/32×(23+17))的表达式树

使用先序、中序、后序遍历树,并把操作数与相关的操作符用括号括起来,得到前缀、中缀、后缀表达式:

前缀表达式

(×(/(-74 10)32)(+ 23 17)) = 80

中缀表达式

(((74 - 10)/32×(23+17)) = 80

后缀表达式(逆波兰表达式)

(((74 10 - )32/)(23 17+)× ) = 80

采用抽象栈状态机(abstract stack machine)来处理后缀表达式(逆波兰表达式)

二叉搜索树

为了更进一步理解保持一棵二叉搜索树平衡的重要性,不妨考虑一下当一棵二叉搜索树变得越来越不平衡的状态。如果是这样的话,查找一个结点的复杂度就变成了O(n),这就相当于从头到尾检索所有的结点。

NP完全问题

没有已知的求解多项式时间的算法,但也无法证明此多项式不存在,这类问题被称为NP完全问题

LRU页面置换算法

第二次机会置换法是实现LRU页面置换算法的一种方式。

它的工作方式是:维护一个当前存在于物理内存中的页面的循环链表。为了简化说明,假设链表中的每个元素只存储一个页码和一个引用值,引用值要么为1要么为0。所有的页面初始引用值都设置为0。每当系统访问页面时(比如,某个进程开始读或写某个页面),该页面的引用值就设置为1.

当需要某个页帧时,操作系统就使用它维护的循环链表以及引用值来判断哪些页面应该释放其页帧。为了确定这一点,开始遍历链表直到找到一个引用值为0的元素。当遍历每一个页面时,操作系统将页面的引用值从1重设回0。一旦它遇到引用值为0的元素,它就找到了一个自从上次遍历链表以来都没有被 系统访问过的页面,因此这个页面就是最近最少使用的页面。

集合覆盖

归并排序

归并排序需要额外的存储空间来运行,这也是它的一个缺点。然而,归并排序对于海量数据处理还是非常有价值的,因为它能够按预期将数据集分开。这使得我们能够将数据集分割为更加可管理的数据,接着用归并排序来处理数据,然后不断地合并数据,在这个过程中并不需要一次存储所有的数据。

多项式插值

求函数近似值的一种方法。其中函数值仅在几个点上已知。该算法的基础是建立级数小于等于n的一个插值多项式pn(z),其中n+1是已知函数值的个数。

最小二乘法

给定函数y(x)=b1x+b0,用来确定b1和b0的估计器方法,使得y(x)是n个点(x0,y0),...,(xn-1,yn-1)的集合的最佳拟合线。最佳拟合线使用最小二乘估计法来最小化每个点(xi,yi),i=0,...,n-1与沿y(x)的相应点(xi,y(xi))之间的垂直距离的平方和。

方程求解

使用牛顿迭代法

LZ77




相关数据结构(其中一种实现)

12位可以让滑动窗口容纳4KB,在一个32字节的缓冲区中,重复的字节不会超过32个字节,即长度为5位,下一个字节保存在【未匹配的符号】字段内。

第一位用1和0来表示在有重复项和没有重复项时数据表示的不同。

旅行商问题

在一幅图中,访问每个顶点一次,并最终返回起始顶点,这个访问的轨迹称为哈密顿圈

要解决旅行商问题,需要用图G=(V,E)作为 模型,寻找图中最短的哈密顿圈。

一种近似地算旅行商路线的方法就是使用最近邻法。其运算方法如下,从一条仅包含起始点的路线开始,将此顶点涂黑。其他顶点为白色,在其它顶点加入此路线中后,再将相应顶点涂黑。接着,对于每个不在路线中的顶点v,要为最后加入路线的顶点u与v之间的边计算权值。回想一下,在旅行商问题中u与v之间边的权值就是u到v之间的距离。这个距离可以用每个顶点的坐标计算得到。



得到的近似解

实际上的最优化效果为:

几何算法

判断线段是否相交

凸包

来自为知笔记(Wiz)

时间: 2024-08-09 23:52:19

《算法精解 C语言描述》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: