??xml version="1.0" encoding="utf-8" standalone="yes"?>久久97超碰色,亚洲福利视频网,亚洲成人tvhttp://www.aygfsteel.com/huyi2006/articles/192023.html胡意胡意Thu, 10 Apr 2008 15:26:00 GMThttp://www.aygfsteel.com/huyi2006/articles/192023.htmlhttp://www.aygfsteel.com/huyi2006/comments/192023.htmlhttp://www.aygfsteel.com/huyi2006/articles/192023.html#Feedback0http://www.aygfsteel.com/huyi2006/comments/commentRss/192023.htmlhttp://www.aygfsteel.com/huyi2006/services/trackbacks/192023.html

介绍Q?/p>

       设计内存池的目标是ؓ了保证服务器长时间高效的q行Q通过对申L间小而申请频J的对象q行有效理Q减内存碎片的产生Q合理分配管理用户内存,从而减系l中出现有效I间_Q而无法分配大块连l内存的情况?/p>

目标Q?/p>

    此次设计内存池的基本目标Q需要满线E安全性(多线E)Q适量的内存泄露越界检查,q行效率不太低于malloc/free方式Q实现对4-128字节范围内的内存I间甌的内存池理Q非单一固定大小对象理的内存池Q?/p>

内存池技术设计与实现

    本内存池的设计方法主要参考SGI的alloc的设计方案,Z适合一般的应用Qƈ在alloc的基上做一些简单的修改?/p>

    Mempool的内存池设计Ҏ如下Q也可参考候捷《深入剖析STL》)

    从系l申请大块heap内存Q在此内存上划分不同大小的区块,q把h相同大小的区块连接v来,l成一个链表。比如A大小的块Q组成链表LQ当甌A大小Ӟ直接从链表L头部Q如果不为空Q上取到一块交l申误,当释放A大小的块Ӟ直接挂接到L的头部。内存池的原理比较简单,但是在具体实现过E中大量的细节需要注意?/p>

    1Q字节对齐?/p>

    Z方便内存池中对象的管理,需要对甌内存I间的进行调_在Mempool中,字节寚w的大ؓ最接近8倍数的字节数。比如,用户甌5个字节,Mempool首先会把它调整ؓ8字节。比如申?2字节Q会调整?4Q对比关pd?/p>

序号

寚w字节

范围

0

8

1-8

1

16

9-16

2

24

17-24

3

32

25-32

4

40

33-40

5

48

41-48

6

56

49-56

7

64

57-64

8

72

65-72

9

80

73-80

10

88

81-88

11

96

89-96

12

104

97-104

13

112

105-112

14

120

113-120

15

128

121-128

Q图1Q?/p>

对于过128字节的申P直接调用malloc函数甌内存I间。这里设计的内存池ƈ不是Ҏ有的对象q行内存理Q只是对甌内存I间,而申请频J的对象q行理Q对于超q?28字节的对象申P不予考虑。这个需要与实际目l合Qƈ不是固定不变的。实现对齐操作的函数如下

static size_t round_up(size_t size)
{
        return (((size)+7) &~ 7);// ?字节寚w
}

2Q构建烦引表

内存池中理的对象都是固定大,现在要管?-128字节的范围内的对象申L_除了采用上面提到的字节对齐外Q还需要变通一下,q就是徏立烦引表Q做法如下;
static _obj*  free_list[16];
创徏一个包?6个_obj*指针的数l,关于_objl构后面详细讲解。free_list[0]记录所有空闲空间ؓ8字节的链表的首地址Qfree_list[1]对应16字节的链表,free_list[2]对应24字节的列表。free_list中的下标和字节链表对应关pd考图1中的“序号”和“对齐字节”之间的关系。这U关p,我们很容易用法计算出来。如?/p>

static size_t freelist_index(size_t size)
{
        return (((size)+7)/7-1);// ?字节寚w
}

    所以,q样当用LL间AӞ我们只是通过上面单的转换Q就可以跌{到包含A字节大小的空闲链表上,如下Q?br />_obj** p = free_list[freelist_index(A)];

3:构徏I闲链表

通过索引表,我们知道mempool中维持着16条空闲链表,q些I闲链表中管理的I闲对象大小分别?Q?6Q?4Q?2Q?0?28。这些空闲链表链接v来的方式完全相同。一般情况下我们构徏单链表时需要创建如下的一个结构体?/p>

struct Obj
{
    Obj *next;
    Char* p;
    Int iSize;
}

next指针指向下一个这Ll构Qp指向真正可用I间,iSize用于只是可用I间的大,在其他的一些内存池实现中,q有更复杂的l构体,比如q包括记录此l构体的上l构体的指针Q结构体中当前用空间的变量{,当用LL间时Q把此结构体d的用LL间中去,比如用户甌12字节的空_可以q样?/p>

Obj *p = (Obj*)malloc(12+sizeof(Obj));
p->next = NULL;
p->p = (char*)p+sizeof(Obj);
p->iSize = 12;

但是Q我们ƈ没有采用q种方式Q这U方式的一个缺点就是,用户甌空间时Q内存池加料太多了。比如用L?2字节Ӟ而真实情冉|内存池向内存甌?2+ sizeof(Obj)=12+12=24字节的内存空_q样费大量内存用在标记内存I间上去Qƈ且也没有体现索引表的优势。Mempool采用的是union方式

union Obj
{
    Obj *next;
    char client_data[1];
}

q里除了把上面的struct修改为unionQƈ把int iSizeLQ同时把char*pQ修改ؓchar client_data[1]Qƈ没有做太多的修改。而优势也恰恰体现在这里。如果采用struct方式Q我们需要维护两条链表,一条链表是Q已分配内存I间链表Q另一条是未分配(I闲Q空间链表。而我们用烦引表和unionl构体,只需要维护一条链表,x分配I间链表。具体如?/p>

索引表的作用有两?Q如上所_l护16条空闲链?Q变相记录每条链表上I间的大,比如下标?的烦引表内维持着是大ؓ24字节的空闲链表。这h们通过索引表减在l构体内记录p所指向I间大小的iSize变量。从而减?个字节?/p>

Union的特性是Q结构内的变量是互斥存在的。再q行状态下Q只是存在一U变量类型。所以在q里sizeof(Obj)的大ؓ4Q难道这里我们也需要把q?字节也加到用LL间中dQ其实不是,如果q样Q我们又Ҏ了union的特性?/p>

当我们构建空闲分配链表时Q我们通过next指向下一个unionl构体,q样我们不用p指针。当把这个结构体分配出去Ӟ我们直接q回client_data的地址Q此时client_data正好指向甌I间的首字节。所以这P我们׃用在用户甌I间上添加Q何东ѝ?/p>


?

    Obj的连接方式如上所C,q样我们无需为用LL间添加Q何内宏V  ?/p>

4Q记录申L间字节数

如果采用面向对象方式Q或者我们在释放内存池的I间时能够明知道释攄间的大小Q无需采用q种方式?/p>


?

在C语言中的free没有传递释攄间大,而可以正释放,在这里也是模仿这U方式,采用q种记录甌I间大小的方式去释放内存。用LL?1操作在字节寚w之前执行Q找到合适空间后Q把首字节改写ؓ甌I间的大,当然1个字节最多纪?56个数Q如果项目需要,可以讄为shortcd或者intcdQ不q这样就需要占用用h较大的空间。当释放内存I间Ӟ首先dq个字节Q获取空间大,q行释放。ؓ了便于对大于128字节对象的大进行合适的释放Q同时也对大?28字节的内存申Pd1字节记录大小。所以现在这里限制了用户内存甌I间不得大于255字节Q不q现在已l满项目要求。当然也可以修改为用shortcd记录甌I间的大?/p>

    // 甌
    *(( unsigned char *)result) = (size_t)n;
    unsigned char * pTemp = (unsigned char*)result;
    ++pTemp;
    result = (_obj*)pTemp;
    return result;

    // 释放
    unsigned char * pTemp = (unsigned char *)ptr;
    --pTemp;
    ptr = (void*)pTemp;
    n = (size_t)(*( unsigned char *)ptr);

5Q内存池的分配原?/p>

在内存池的设计中Q有两个重要的操作过E?Qchunk_allocQ申请大块内存,2Qrefill回填操作Q内存池初始化化时ƈ不是为烦引表中的每一w创徏I闲分配链表Q这个过E会推迟刎ͼ只有用户提取h时才会创L分配链表。详l参考如下代码(在sgi中stl_alloc.h文g中你也可以看到这两个函数Q,主要步骤在注释中已经说明?/p>

/**
* @bri: 甌大块内存Qƈq回size*(*nobjs)大小的内存块
* @param: size,round_up寚w后的大小,nobjs
* @return: q回指向W一个对象内存指?br />*/
static char* chunk_alloc(size_t size, int *nobjs)
{
     /**< q回指针 */
     char* __result;
     /**< 甌内存块大?*/
     size_t __total_bytes = size *(*nobjs);
     /**< 当前内存可用I间 */
     size_t __bytes_left = _end_free - _start_free;

     /**< 内存池中q有大片可用内存 */
     if (__bytes_left >= __total_bytes)
     {
         __result = _start_free;
         _start_free += __total_bytes;
         return (__result);
     }
     /**< 臛_q有一个对象大的内存I间 */
     else if (__bytes_left >= size)
     {
         *nobjs = (int)(__bytes_left/size);
         __total_bytes = size * (*nobjs);
         __result = _start_free;
         _start_free += __total_bytes;
         return (__result);
     }
     /**< 内存池中没有MI间 */
     else
     {
         /**< 重新甌内存池的大小 */
         size_t __bytes_to_get = 2 * __total_bytes + round_up(_heap_size >> 4);
         /**< 把内存中剩余的空间添加到freelist?*/
         if(__bytes_left > 0)
         {
              _obj *VOLATILE* __my_free_list = 
                   _free_list + freelist_index(__bytes_left);
              ((_obj*)_start_free)->free_list_link =
*__my_free_list;
              *__my_free_list = (_obj*)_start_free;
         }
         // 甌新的大块I间
         _start_free = (char*)malloc(__bytes_to_get);
         /*=======================================================================*/
         memset(_start_free,0,__bytes_to_get);
         /*=======================================================================*/
         // pȝ内存已经无可用内存,那么从内存池中压~内?br />         if(0 == _start_free)
         {
              size_t __i;
              _obj *VOLATILE* __my_free_list;
              _obj *__p;
              /**< 从freelist中逐项查可用空?此时只收集比size对象大的内存I间) */
              for (__i = size; __i <= (size_t)__MAX_BYTES; __i += __ALIGN)
              {
                   __my_free_list = _free_list + freelist_index(__i);
                   __p = *__my_free_list;
                   /**< 扑ֈI闲?*/
                   if (__p != 0)
                   {
                       *__my_free_list = __p->free_list_link;
                       _start_free = (char*)__p;
                       _end_free = _start_free + __i;
                       return (chunk_alloc(size,nobjs));
                   }
              }
              _end_free = 0;
              /**< 再次甌内存Q可能触发一个异?*/
              _start_free = (char*)malloc(__bytes_to_get);
         }
         /**< 记录当前内存池的定w */
         _heap_size += __bytes_to_get;
         _end_free = _start_free + __bytes_to_get;
         return (chunk_alloc(size,nobjs));
     }
}

/*=======================================================================*/
/**
 * @bri: 填充freelist的连接,默认填充20?br /> * @param: __nQ填充对象的大小Q?字节寚w后的value
 * @return: I闲
 */
static void* refill(size_t n)
{
     int __nobjs = 20;
     char* __chunk = (char*)chunk_alloc(n, &__nobjs);
     _obj *VOLATILE* __my_free_list;
     _obj *VOLATILE* __my_free_list1;
     _obj * __result;
     _obj * __current_obj;
     _obj * __next_obj;
     int __i;
     // 如果内存池中仅有一个对?br />     if (1 == __nobjs) 
         return(__chunk);
     __my_free_list = _free_list + freelist_index(n);
     /* Build free list in chunk */
     __result = (_obj*)__chunk;
     *__my_free_list = __next_obj = (_obj*)(__chunk + n);
     __my_free_list1 = _free_list + freelist_index(n);
     for (__i = 1;; ++__i)
     {
         __current_obj = __next_obj;
         __next_obj = (_obj*)((char*)__next_obj+n);
         if(__nobjs - 1 == __i)
         {
              __current_obj->free_list_link = 0;
              break;
         }else{
              __current_obj->free_list_link = __next_obj;
         }
     }
     return(__result);
}

l过上面操作后,内存池可能会成ؓ如下的一U状态。从图上我们可以看到Q已l构Z8Q?4Q?8Q?28字节的空闲分配链表,而其他没有分配空闲分配链表的他们的指针都指向NULL。我们通过判断索引表中的指针是否ؓNULLQ知道是否已l构建空闲分配表或者空闲分配表是否用完Q如果此处指针ؓNULLQ我们调用refill函数Q重新申?0个这样大的内存I间Qƈ把他们连接v来。在refill函数内,我们要查看大内存中是否有可用内存Q如果有Qƈ且大合适,p回给refill函数?br />


?

 

    6Q线E安?br />    采用互斥体,保证U程安全?br />
内存池测?/p>

    内存池的试主要分两部分试1Q单U程下malloc与mempool的分配速度Ҏ2Q多U程下malloc和mempool的分配速度ҎQ我们分?Q?0Q?6个线E进行测试了?br />    试环境Q操作系l:windows2003+sp1QVC7.1+sp1Q硬件环境:intel(R) Celeron(R) CPU 2.53GHz,512M物理内存?br />
    甌内存I间讑֮如下
#define ALLOCNUMBER0 4
#define ALLOCNUMBER1 7
#define ALLOCNUMBER2 23
#define ALLOCNUMBER3 56
#define ALLOCNUMBER4 10
#define ALLOCNUMBER5 60
#define ALLOCNUMBER6 5
#define ALLOCNUMBER7 80
#define ALLOCNUMBER8 9
#define ALLOCNUMBER9 100

    Malloc方式和mempool方式均用如上数据进行内存空间的甌和释放。申误E,每次循环甌释放上述数据20?br />    我们对malloc和mempoolQ分别进行了如下甌ơ数的测试(单位ZQ?/p>

2

10

20

30

40

50

80

100

150

200

malloc和mempool在单U程Q多U程QreleaseQdebug版的各种试数据QŞ成如下的l计?


?

可以看到mempool无论在多U程q是在单U程情况下,mempool的速度都优于malloc方式的直接分配?/p>

    Malloc方式debug模式下,在不同的U程下,q行旉如下Q通过囄可知Qmalloc方式Q在debug模式下,甌I间的速度和多U程的关pM大。多U程方式Q要略快于单U程的运行实现?/p>


?

    Malloc方式release模式试l果如下?/p>


?

多线E的优势Q逐渐体现出来。当执行200wơ申请和释放Ӟ多线E要比单U程?500ms左右Q?Q?0Q?6个线E之间的差别q不是特别大。不q整体感?个线E的q行旉要稍微高?0Q?6个线E的情况下,意味着q程中线E越多用在线E切换上的时间就多?/p>

下面是mempool在debug试l果


?

    下面是mempool在release模式下的试l果


?

    以上所有统计图中所用到的数据,是我们测试三ơ后q_倹{?/p>

通过上面的测试,可以知道mempool的性能基本上超q直接malloc方式Q在200wơ申请和释放的情况下Q单U程release版情况下Qmempool比直接malloc?10倍。而在4个线E情况下Qmempool要比直接malloc?倍左叟뀂以上测试只是申请速度的测试,在不同的压力情况下,试l果可能会不同,试l果也不能说明mempool方式比malloc方式E_?br />
    结Q内存池基本上满_期设计目标,但是她ƈ不是完美的,有缺P比如,不能甌大于256字节的内存空_无内存越界检查,无内存自动回~功能等。只是这些对我们的媄响还不是那么重要?/p>

׃q是一个公叔R目,代码涉及版权Q所以不能发布出来。如果你惛_自己的内存池Q可以与我联pugg_xchj#hotmail.com.



胡意 2008-04-10 23:26 发表评论
]]>
若干l典的字W串哈希函数 http://www.aygfsteel.com/huyi2006/articles/191348.html胡意胡意Mon, 07 Apr 2008 11:57:00 GMThttp://www.aygfsteel.com/huyi2006/articles/191348.htmlhttp://www.aygfsteel.com/huyi2006/comments/191348.htmlhttp://www.aygfsteel.com/huyi2006/articles/191348.html#Feedback0http://www.aygfsteel.com/huyi2006/comments/commentRss/191348.htmlhttp://www.aygfsteel.com/huyi2006/services/trackbacks/191348.html阅读全文

胡意 2008-04-07 19:57 发表评论
]]>
SQLite数据库文件格式分?B树的基本l织)http://www.aygfsteel.com/huyi2006/articles/189050.html胡意胡意Thu, 27 Mar 2008 08:37:00 GMThttp://www.aygfsteel.com/huyi2006/articles/189050.htmlhttp://www.aygfsteel.com/huyi2006/comments/189050.htmlhttp://www.aygfsteel.com/huyi2006/articles/189050.html#Feedback0http://www.aygfsteel.com/huyi2006/comments/commentRss/189050.htmlhttp://www.aygfsteel.com/huyi2006/services/trackbacks/189050.html此分析称为简易版Q因为后面还计划分析一个更复杂的数据库文gQ以深入理解SQLite数据库B树实现的l构Q从易的开始不׃ؓ一U好的学习方法,q里的简易版本文件是指大ؓ2K字节Q即每个B树页1K字节Q共两个B树页Q补充说明一下,q里的B树页是指经典数据结构书上所讲的B树节点,在这里称为页是因为SQLite在实现B树时是使用page的概忉|l织的?
创徏Ҏ如下Q?br />CREATE TABLE tbl1(one varchar(10),two varchar(10));
INSERT INTO "tbl1" VALUES('first', 'xxx');
INSERT INTO "tbl1" VALUES('second', 'yyy');

然后退出,用UltraEdit打开q个数据库文Ӟ
00000000h: 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 ; SQLite format 3.
00000010h: 04 00 01 01 00 40 20 20 00 00 00 07 00 00 00 00 ; .....@  ........
00000020h: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 01 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ; ................
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000060h: 00 00 00 00 0D 00 00 00 01 03 B8 00 03 B8 00 00 ; ..........?.?.
00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
q中间部分全部都是零。省去!
000003a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000003b0h: 00 00 00 00 00 00 00 00 46 01 06 17 15 15 01 71 ; ........F......q
000003c0h: 74 61 62 6C 65 74 62 6C 31 74 62 6C 31 02 43 52 ; tabletbl1tbl1.CR
000003d0h: 45 41 54 45 20 54 41 42 4C 45 20 74 62 6C 31 28 ; EATE TABLE tbl1(
000003e0h: 6F 6E 65 20 76 61 72 63 68 61 72 28 31 30 29 2C ; one varchar(10),
000003f0h: 74 77 6F 20 76 61 72 63 68 61 72 28 31 30 29 29 ; two varchar(10))
     q是W一个B树页Q这个B树页里存放了表sqlite_master的信息,q就是SQLite数据库的pȝ表了?br />下面分析一下这些二q制的具体涵义,SQLitel一采用大端法来表示数据Q不同与一般intel机器的小端法了:
偏移地址   大小    涵义
 0          16     "SQLite format 3\000"
16           2     400HQ?024个字节,每个面的字节数 
18           2     0101H表示版本可已
20           1     每页末端的未用空_q里为零表示数据都是从每|后一个字节开始存?br />21           1     最大负载分片数Q类gIP分片Q一存不下Q要分片
22           1     最负载分片数
23           1     最叶子负载分片数
24           4     文g修改计数Q用于实现ƈ行访?br />28           4     保留未用
32           4     W一个freelist?br />36           4     文g中的freelist|
40          60     q里未用
上面的这一百个字节UCؓ数据库文件的文g_q个文g头只有第一个B树页才有Q后面的每一个B树页都没有这个结构,后面每一늻构都相同Q?br />依次为:B树页头结构,B树指针结构,未用I间QB树实际数据负载?br />q里和经典数据结构书上的B树结构有些出入,q里的目的是实际应用方便Q而书上的l构目的是解释清楚B树的原理。所以有些不同:
一般书上讲的一个B树页的结构ؓQ指针,数据Q指针,数据Q指针,数据Q?..Q指?br />而SQLitel织为:指针Q指针,指针Q?..Q指针,数据Q数据,...数据?br />W一个页面中?0000060h行第五个字节开始就表示B树页头结构了Q?br />偏移地址   大小    涵义
0           1      0DhQ?101b各位意义?: intkey, 2: zerodata, 4: leafdata, 8: leaf
1           2      W一个空闲块的字节偏U量Q这里ؓ0
3           2      01Q这个B树页存放的记录数?个,即系l表中只存放了一条记录,因ؓ只创Z一个表tbl1
5           2      负蝲区首地址Q?3B8Q往下看?00003b0h行那?6是负蝲区的开始了
7           1      分片敎ͼq里数据,不考虑Q所以ؓ0
?000006Bh偏移处B数头l束了,接下来的是B数指针结构了Q此处只有一,只有一个指?3B8h处?br />?00003B8h偏移到结束都是sqlite_master表的实际数据了。当然这些数据也是有l构的?6h表示q条记录?0个字节,除去其本w?6Q和后面?1是烦引外Q整个记录刚好是70个字节,01索引后面都是payload负蝲数据了?br />如法炮制Q下面列出第二个B树页Q?br />00000400h: 0D 00 00 00 02 03 E5 00 03 F3 03 E5 00 00 00 00 ; ......?.??...
00000410h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
q中间部分全部ؓ零。省去!
000007d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000007e0h: 00 00 00 00 00 0C 02 03 19 13 73 65 63 6F 6E 64 ; ..........second
000007f0h: 79 79 79 0B 01 03 17 13 66 69 72 73 74 78 78 78 ; yyy.....firstxxx
׃不是W一,所以不存在文g头的100个字节了Q一开始就是B树页头结构了Q这里有两个指针03F3?3E5Q其它的和上面一栗整个数据库理pȝ是准确无误地对q个文gq行理?br />q一步的工作Q只有数据多了,才能看出B树组l的好处Q查找,删除Q增加的快速!把这个文件变大再分析Q?/div>

胡意 2008-03-27 16:37 发表评论
]]>行编辑器的数据结构运用-Q-堆栈http://www.aygfsteel.com/huyi2006/articles/160348.html胡意胡意Tue, 13 Nov 2007 14:00:00 GMThttp://www.aygfsteel.com/huyi2006/articles/160348.htmlhttp://www.aygfsteel.com/huyi2006/comments/160348.htmlhttp://www.aygfsteel.com/huyi2006/articles/160348.html#Feedback0http://www.aygfsteel.com/huyi2006/comments/commentRss/160348.htmlhttp://www.aygfsteel.com/huyi2006/services/trackbacks/160348.html/****************a simple stack**********************************/

#include <stdio.h>

#define STACK_INIT_SIZE 100
#define STACKINCREMENT  10
typedef int bool;
#define TRUE   1
#define FALSE  0
typedef struct
{
 char *base;
 char *top;
 int stacksize;
}sqStack;

//=======================function protoType=============================
bool InitStack(sqStack *stk);
bool DestroyStack(sqStack *stk);
bool ClearStack(sqStack *stk);
bool StackEmpty(sqStack stk);
int  StackLength(sqStack stk);
bool GetTop(sqStack stk, char *item);
bool Push(sqStack *s, char item);
bool Pop(sqStack *s, char *item);

bool InitStack(sqStack *stk)
{
 stk->base = (char *)malloc(STACK_INIT_SIZE * sizeof(char));
 if (!stk->base)
 return FALSE;
 stk->top = stk->base;
 stk->stacksize = STACK_INIT_SIZE;
 return TRUE;
}

bool GetTop(sqStack stk, char *item)
{
 if (stk.top == stk.base)
 return FALSE;
 item = (stk.top-1);
 return TRUE;
}

bool Push(sqStack *stk, char item)
{
 if (stk->top - stk->base >= stk->stacksize)
 {
  printf("allocate New Mem\n");
  stk->base = (char *)realloc(stk->base, (stk->stacksize + STACKINCREMENT)* sizeof(char));
  if (!stk->base)
  return FALSE;
  stk->top = stk->base + stk->stacksize;
  stk->stacksize += STACKINCREMENT;
 }
 *stk->top = item;
 stk->top++;
 return TRUE;
}

bool Pop(sqStack *stk, char* item)
{
 if (stk->top == stk->base)
 return FALSE;
 stk->top--;
 *item = *(stk->top);
 return TRUE;
}

bool StackEmpty(sqStack stk)
{
 if (stk.top == stk.base)
 return TRUE;
 else
 return FALSE;
}

bool ClearStack(sqStack *stk)
{
 stk->top = stk->base;
 memset(stk->base, 0, sizeof(char));
 if (stk->top)
 return TRUE;
 else
 return FALSE;
}
bool DestroyStack(sqStack *stk)
{
 free(stk->base);
 printf("free memery\n");
 return TRUE;
}    

int main(int argc, char** argv)
{
 sqStack stk;
 char ch;
 InitStack(&stk);
 ch = getchar();
 while(ch != EOF)
 {
  while(ch != EOF && ch != '\n')
  {
   switch (ch)
   {
      case '#':
    Pop(&stk, &ch);
    break;
      case '@':
       ClearStack(&stk);
       break;
      case 'q':       
        DestroyStack(&stk);
        exit(1);
        break;       
      default:
       Push(&stk, ch);
   }
   ch = getchar();
  }
  ClearStack(&stk);
  if (ch != EOF)
  ch = getchar();
 }
 DestroyStack(&stk); 
 return 1;
}

特别要注意的是堆栈的中操作栈的|在就是对内存的操?/p>

胡意 2007-11-13 22:00 发表评论
]]>
KMP字符串匹配算?/title><link>http://www.aygfsteel.com/huyi2006/articles/114588.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Sun, 29 Apr 2007 07:52:00 GMT</pubDate><guid>http://www.aygfsteel.com/huyi2006/articles/114588.html</guid><wfw:comment>http://www.aygfsteel.com/huyi2006/comments/114588.html</wfw:comment><comments>http://www.aygfsteel.com/huyi2006/articles/114588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/huyi2006/comments/commentRss/114588.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/huyi2006/services/trackbacks/114588.html</trackback:ping><description><![CDATA[ <p>KMP法的关键是Ҏl定的模式串W[1,m],定义一个next函数。next函数包含了模式串本n局部匹配的信息?br />   KMP法的基本思想是:假设在模式匹配的q程中,执行T[i]和W[j]的匹配检查。若T[i]=W[j]Q则l箋查T[i+1]和W[j+1]是否匚w。若T[i]<>W[j]Q则分成两种情况Q若j=1Q则模式串右UM位,查T[i+1]和W[1]是否匚wQ若1<j<=mQ则模式串右Uj-next(j)位,查T[i]和W[next(j)]是否匚w。重复此q程直到j=m或i=nl束?/p> <p>/**************************************<br /> *<br /> *  KMP字符串匹配算?br /> *<br /> *<br /> **************************************/<br />#include <stdio.h><br />#include <string.h><br />int next[10];<br />void getnext(char *p)<br />{<br /> int idx_p, len_p, k;<br /> <br /> idx_p = 0;<br /> len_p = strlen(p);<br /> k = -1;<br /> next[0] = -1;<br /> <br /> while(idx_p < len_p -1)<br /> {<br />  if ((k == -1) || *(p+idx_p) == *(p+k)) <br />  {<br />   idx_p = idx_p + 1;<br />   k = k + 1;<br />   next[idx_p] = k; <br />  }<br />  else<br />  {<br />   k = next[k]; <br />  }<br /> } <br />}<br />int kmp(char *s, char *p)<br />{<br /> int len_p, len_s, idx_p, idx_s;<br /> <br /> len_p = strlen(p);<br /> len_s = strlen(s);<br /> idx_p = idx_s = 0;<br /> <br /> while ((idx_p < len_p) && (idx_s < len_s))<br /> {<br />  /* 字符匚w或者要比较p中的W一个字W?*/<br />  if ((idx_p == -1) || *(p+idx_p) == *(s+idx_s))<br />  {<br />   idx_p = idx_p + 1; idx_s = idx_s +1; <br />  } <br />  else<br />  {<br />   idx_p = next[idx_p]; <br />  }<br /> }<br /> if (idx_p >= len_p)<br /> {<br />  return (idx_s - len_p); <br /> }<br /> else <br /> {<br />  return -1; <br /> }<br />}<br />int main()<br />{<br /> int pos, i;<br /> char s[50] = "abaaaabcabcacb";<br /> char p[10] = "aaaabca";<br /> <br /> getnext(p);<br /> if ((pos = kmp(s, p)) == -1)<br /> {<br />  fprintf(stderr, "String \"%s\" doesn't contain Pattern \"%s\"!\n", s, p); <br /> }<br /> else<br /> {<br />  printf("String \"%s\" contains Pattern \"%s\".\n The position of fisrt occur is %d\n", s, p, pos);<br />  printf("%s\n", s);<br />  for (i = 0; i < pos; i++)<br />   printf(" "); <br />  printf("%s\n", p);<br /> }<br /> return 0; <br />}<br /></p> <img src ="http://www.aygfsteel.com/huyi2006/aggbug/114588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/huyi2006/" target="_blank">胡意</a> 2007-04-29 15:52 <a href="http://www.aygfsteel.com/huyi2006/articles/114588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͼƬ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ī</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ϲ</a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">˷</a>| <a href="http://" target="_blank">̳</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ƹ</a>| <a href="http://" target="_blank">̫ԭ</a>| <a href="http://" target="_blank">ɳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͼ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʲ</a>| <a href="http://" target="_blank">Զ</a>| <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">׿</a>| <a href="http://" target="_blank">ֹ</a>| <a href="http://" target="_blank">²</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̨ǰ</a>| <a href="http://" target="_blank">Ȫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>