C++ STL链表排序问题

这是一段从STL中摘录下来的代码,它声称对链表做了排序的工作: template<typename _Tp, typename _Alloc> void list<_Tp,_Alloc>:: sort() { // Do nothing if the list has length 0 or 1. if (this->_M_impl._M_node._M_next != &this->_M_impl._M
分类: 其他 发布时间: 11-18 07:56 阅读次数: 0

C++标准模板库STL:僵化的代码

不得不说,跟C/C++一贯的灵活的风格相反,C++标准模板库设计的极不灵活。STL的功能很难同新设计的代码融洽的融合在一起。比如,你要写个快速排序的程序。由于选择了vector来表示数组。你不得不这样写:void qsort(vector &v, int start, int len);而原来只要写:void qsort(int *start, int len); 多传了一个参数。而qsort里面是递归调用。这样明显损失了性能。要不就这样写:void qsort(vector::ite
分类: 其他 发布时间: 11-18 07:56 阅读次数: 0

C++的自动内存管理

内存泄漏问题,过去在C语言曾是一个令人头痛的问题。但在C++却可以自动的管理。方法就是重载全局的new,在分配一个对象的时候,同时把它的内存地址挂在一个zone上。#include <stdio.h>#include <string.h>struct zone { struct link { struct link *p; template <typename T>
分类: 其他 发布时间: 11-18 07:56 阅读次数: 0

C语言中返回局部函数问题

如何把函数中的一部分代码作为局部函数来返回,这是跟体系架构密切相关的。需要了解运行栈的格式,并使用一些汇编指令。还要防止编译器对代码做不可预测的优化。无论如何从函数中返回局部函数是可能的。这个一个x86上的例子:#include <stdio.h>static int getip(){ __asm__( "movl 4(%ebp), %eax\r\n" );}#define GET_LOCAL_ENTRY \
分类: 其他 发布时间: 11-18 07:56 阅读次数: 0

用list和auto_ptr进行自动内存管理

STL的auto_ptr具有自动管理单个内存对象的能力。list又可以管理一组对象。两者加起来,是不是就可以对一组对象进行自动内存管理了呢?这个想法看起来不错。一切都是信手拈来。代码看起来是这样子:#include <list>#include <memory>#include <stdio.h>using namespace std;struct node { char name[10]; int val;
分类: 其他 发布时间: 11-18 07:55 阅读次数: 0

Linux内核中的spin_lock

在Linux内核中,spin_lock是最基本的锁机制。spin_lock也翻译成自旋锁。它的用法是非常直观的。Linux提供了3个例程来使用它:spin_lock(): 加锁。如果遇到自旋锁已经锁定,不停重试直到成功。spin_unlock(): 解锁。spin_trylock(): 加锁。如果遇到自旋锁已经锁定,不重试,返回失败码。另外,为了在中断环境使用,还提供了两个宏:spin_lock_irqsave():spin_unlock_irqrestore():分别在加锁时关中断,和在解锁
分类: 其他 发布时间: 11-18 07:55 阅读次数: 0

牛顿下山法求解根式

数值计算课程老师讲了牛顿下山法。在根附近,从y曲线任取一点。得到(x0, y0)。然后从这一点作切线。这是一条直线。求出它和x轴的交点(x1, 0)。从y曲线取x1处的一点,得到(x1, y1) 。这是比原更接近于根(x*,0)的值。把(x1, y1)用作(x0, y0)如此得到迭代,获得序列(xi, yi)。越到后面的xi越接近x*, yi越接近0。由此推导出一个迭代计算公式:x[i+1]= (0-y[i])/y'[i] + x[i]如果是求根号2,y的函数是y = x * x -2代入后,
分类: 其他 发布时间: 11-18 07:55 阅读次数: 0

绑定文件的数组

对于大容量的数组,可以把它和一个文件绑定,内存中只缓存一些正在使用的片断。这样,数组的容量可以非常大。这是C++的一个实现:#include <stdio.h>#include <stdlib.h>#include <string.h>class filearray {private: struct page { int pageno; int tag;
分类: 其他 发布时间: 11-18 07:55 阅读次数: 0

10度角的三角函数计算

特殊角30,60,90度的三角函数大家都很熟悉了。15度角是30度的半角,利用半角公式也可以很容易推导出来,它等于,sin15 = (sqrt(6)-sqrt(2))/4。1/4的根号6 -根号2。数值上是0.258819。现在来推导sin10度的值。利用两角和的三角公式,sin30 = sin20cos10 + cos20sin10 = 2sin10cos10cos10+(2cos10cos10-1)sin10 =1/2令x=sin10,得方程:4x(1-xx)-x =1/2*即,8xxx
分类: 其他 发布时间: 11-18 07:54 阅读次数: 0

10度角的三角函数计算(续)

用方程8xxx -6x +1 =0求得10度角的三角函数sin10之后。还有一个遗留问题需要讨论一下。就是这个3次方程8xxx -6x +1 =0是否还有其他两个解?如果有,是多少?因为已经知道了sin10是这个方程的一个解了。可以用多项式除法把8xxx -6x +1因式分解。(8xxx -6x +1)/(x-sin10)除法的结果是,商: 8x*x +8sin10 *x + 8sin10sin10 -6余数: 8sin10sin10sin10 -6sin10 +1, 由sin10是方程8xx
分类: 其他 发布时间: 11-18 07:54 阅读次数: 0

Vector的应用:带删除标记的vector

在正则表达式识别的过程中,需要同时跟踪多个正则表达式的识别状态。最自然的做法是用n个元素的指针数组同时跟踪n个识别路径。当输入的字符跟识别路径上接受的输入不符时,这一路的指针失效。当识别路径上遇到ε字符时,这一路的指针发生分叉。STL的vector 能有效的进行自动管理内存,比较适合用来存储这种个数不确定的动态指针数组。为了最小化删除一个指针在数组内产生的移动开销,使用一个删除标记来管理失效的指针。这是对STL的vector 改造后的实现:#include <vector>using
分类: 其他 发布时间: 11-18 07:54 阅读次数: 0

自动管理迭代器的容器

STL的容器实现了迭代器的分离,这样提高了效率。但实际使用时也带来了一些困惑。因为迭代器在使用时,并不显示指出它在引用哪个容器。而且当容器失效时,迭代器也不一起丢弃,不小心就造成误用。可以考虑的方案是,让容器自动管理迭代器。当需要一个迭代器时,让容器分配这个迭代器,把迭代器存在容器里,而把它的Handle返回给客户。这样当容器销毁时,迭代器也一起销毁了。同时,为了显示指出迭代器引用哪个容器,重载operator[]。这里暂且沿用前面讨论过的“带有删除标记的vector”来管理迭代器的分配,用list为例
分类: 其他 发布时间: 11-18 07:54 阅读次数: 0

STL中的红黑树

STL中的set、map都通过红黑树实现。红黑树的类型实际上是可以拿出来用的。用起来也是容易的。因为不是标准规定的容器,具体的名字可能会略有的差别。例子最后演示了迭代器find()。这个地方语法上可以修改,但不能随便修改,因为会破坏key的排序。#include <stdio.h>#include <set>using namespace std;typedef _Rb_tree<int, int, _Identity<int>, less<in
分类: 其他 发布时间: 11-18 07:53 阅读次数: 0

反向使用递推关系的求值

下面这道积分题的计算,随着n的增大,如果用I(n) = 1- n I(n-1)来算,即文中的第一种算法,误差很快积累,最后计算就失效了。所以要第2种算法,倒过来推算。用I(n-1) = 1/n - I(n) 来推算。那么倒过来用递算怎么用呢?怎么才能先求出I7,然后用它一个一个求出I6,I5,…,I0呢?观察被积函数。在[0, 1]之间,随着n增大,x^n越来越小。因此积分I(n)总是小于I(n-1),并且单调的趋向于0。所以有I(无穷大)=0。因而可以用0来估计n较大的I(n),而不用计算。这里x的初
分类: 其他 发布时间: 11-18 07:53 阅读次数: 0

大角的三角函数

三角函数是种周期函数。超出周期的大角可以减去周期之后,转换到一个周期之内来计算。然而… …现在来计算sin(100000000(弧度))的值:a=10000.0;a*=a;print a;100000000.000000pi=3.1415926;n = ceil(a/(2*pi));print n;15915495r = a-2*pi*n;print r;-2.634674print sin(r);-0.485486得到的结果是没有意义的,因为pi是无理数,取pi=3.1
分类: 其他 发布时间: 11-18 07:53 阅读次数: 0

浮点数的指数函数的计算

整数指数的计算是直观的。a的n次方就是n个a相乘。现在来看小数部分。一个10进制数可以写作 0.f1f2f3…fi…。数位f1,f2,f3… 是0-9的数字。它有唯一一个2进制表示,记作0.b1b2b3…bi…。数位b1,b2,b3…是数字0或1。因为同底数的数相乘,底数不变,指数相加。于是可以把指数运算拆解成乘法运算。以2的0.9次方为例,现在来求这个值:a=2;exp=0.9;for(i=0; i<46; i++) { if (i==0) {
分类: 其他 发布时间: 11-18 07:53 阅读次数: 0

浮点数的对数运算计算

对数是指数运算的逆运算。知道了指数运算怎么计算,对数运算也就很容易计算了。下面以计算ln(10)的值为例,演示对数运算的计算。r=0.0;i=20;while(i>0) { r = (1-r)/i; i--;}e = 1/(1-r);print e;a=e, b=10;r=0;while(b>a) { b/=a;r++;}print r;p = 0.5;for(i=0; i<46; i++) { a = a**0.5; if (b>a) {
分类: 其他 发布时间: 11-18 07:52 阅读次数: 0

浮点数开方运算的快速计算

浮点数开方的快速计算的代码是:double fast2(double x){ union P { double x; unsigned long i[2]; }; double a; union P x0; a = x/2; x0.x = x; x0.i[1] = ((x0.i[1] &(0xffefffff>&g
分类: 其他 发布时间: 11-18 07:52 阅读次数: 0

使用大整数进行高精度计算

仍然以求 ln(10)的值为例。为了算出 ln(10)的100小数,把所有数字放大10的100次方倍计算。int main(){ big scaled_1(100000000); scaled_1 = scaled_1 * scaled_1 * scaled_1 * 10; scaled_1 *= scaled_1; scaled_1 *= scaled_1; big e; big p;
分类: 其他 发布时间: 11-18 07:52 阅读次数: 0

缠绕问题

在实际开发中,哪怕是最简单的问题,通常也是缠绕的。这也是让程序员最为费心的问题之一。比如识别注释。注释以 /*开始,然后什么也不用管,直到遇到*/结束。自C++发明以来,又增加了//前导的单行注释。但是光根据这样的注释规则并不能识别注释,因为源程序中还有字符串。字符串中含有的注释符并不作为注释解释。所以识别注释必须同时识别字符串。字符串的格式是以"开始,然后是任意字符,直到再以引号结束。为了避免过于繁琐,这里用lex文法来描述这个问题。lex的格式是:  模式  识别动作于是,是这样一些规则:%%
分类: 其他 发布时间: 11-18 07:52 阅读次数: 0