﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-井泉-随笔分类-数据结构</title><link>http://www.cppblog.com/zjj2816/category/2051.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 18:49:16 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 18:49:16 GMT</pubDate><ttl>60</ttl><item><title>qsort函数应用大全 七种qsort排序方法 </title><link>http://www.cppblog.com/zjj2816/archive/2006/08/29/11816.html</link><dc:creator>井泉</dc:creator><author>井泉</author><pubDate>Tue, 29 Aug 2006 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/zjj2816/archive/2006/08/29/11816.html</guid><wfw:comment>http://www.cppblog.com/zjj2816/comments/11816.html</wfw:comment><comments>http://www.cppblog.com/zjj2816/archive/2006/08/29/11816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zjj2816/comments/commentRss/11816.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zjj2816/services/trackbacks/11816.html</trackback:ping><description><![CDATA[&lt;本文中排序都是采用的从小到大排序&gt; <br /><br />一、对int类型数组排序 <br /><br />int num[100]; <br /><br />Sample: <br /><br />int cmp ( const void *a , const void *b ) <br />{ <br />return *(int *)a - *(int *)b; <br />} <br /><br />qsort(num,100,sizeof(num[0]),cmp); <br /><br />二、对char类型数组排序（同int类型） <br /><br />char word[100]; <br /><br />Sample: <br /><br />int cmp( const void *a , const void *b ) <br />{ <br />return *(char *)a - *(int *)b; <br />} <br /><br />qsort(word,100,sizeof(word[0]),cmp); <br /><br />三、对double类型数组排序（特别要注意） <br /><br />double in[100]; <br /><br />int cmp( const void *a , const void *b ) <br />{ <br />return *(double *)a &gt; *(double *)b ? 1 : -1; <br />} <br /><br />qsort(in,100,sizeof(in[0]),cmp)； <br /><br />四、对结构体一级排序 <br /><br />struct In <br />{ <br />double data; <br />int other; <br />}s[100] <br /><br />//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种，参考上面的例子写 <br /><br />int cmp( const void *a ,const void *B) <br />{ <br />return (*(In *)a)-&gt;data &gt; (*(In *)B)-&gt;data ? 1 : -1; <br />} <br /><br />qsort(s,100,sizeof(s[0]),cmp); <br /><br />五、对结构体二级排序 <br /><br />struct In <br />{ <br />int x; <br />int y; <br />}s[100]; <br /><br />//按照x从小到大排序，当x相等时按照y从大到小排序 <br /><br />int cmp( const void *a , const void *b ) <br />{ <br />struct In *c = (In *)a; <br />struct In *d = (In *)b; <br />if(c-&gt;x != d-&gt;x) return c-&gt;x - d-&gt;x; <br />else return d-&gt;y - c-&gt;y; <br />} <br /><br />qsort(s,100,sizeof(s[0]),cmp); <br /><br />六、对字符串进行排序 <br /><br />struct In <br />{ <br />int data; <br />char str[100]; <br />}s[100]; <br /><br />//按照结构体中字符串str的字典顺序排序 <br /><br />int cmp ( const void *a , const void *b ) <br />{ <br />return strcmp( (*(In *)a)-&gt;str , (*(In *)B)-&gt;str ); <br />} <br /><br />qsort(s,100,sizeof(s[0]),cmp); <br /><br />七、计算几何中求凸包的cmp <br /><br />int cmp(const void *a,const void *B) //重点cmp函数，把除了1点外的所有点，旋转角度排序 <br />{ <br />struct point *c=(point *)a; <br />struct point *d=(point *)b; <br />if( calc(*c,*d,p[1]) &lt; 0) return 1; <br />else if( !calc(*c,*d,p[1]) &amp;&amp; dis(c-&gt;x,c-&gt;y,p[1].x,p[1].y) &lt; dis(d-&gt;x,d-&gt;y,p[1].x,p[1].y)) //如果在一条直线上，则把远的放在前面 <br />return 1; <br />else return -1; <br />} <br /><br />PS: <br /><br />其中的qsort函数包含在&lt;stdlib.h&gt;的头文件里，strcmp包含在&lt;string.h&gt;的头文件里<img src ="http://www.cppblog.com/zjj2816/aggbug/11816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zjj2816/" target="_blank">井泉</a> 2006-08-29 11:58 <a href="http://www.cppblog.com/zjj2816/archive/2006/08/29/11816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 C/C++ 中如何构造通用的对象链表</title><link>http://www.cppblog.com/zjj2816/archive/2006/06/26/9034.html</link><dc:creator>井泉</dc:creator><author>井泉</author><pubDate>Mon, 26 Jun 2006 11:37:00 GMT</pubDate><guid>http://www.cppblog.com/zjj2816/archive/2006/06/26/9034.html</guid><wfw:comment>http://www.cppblog.com/zjj2816/comments/9034.html</wfw:comment><comments>http://www.cppblog.com/zjj2816/archive/2006/06/26/9034.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zjj2816/comments/commentRss/9034.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zjj2816/services/trackbacks/9034.html</trackback:ping><description><![CDATA[一个简化的问题示例<br /><br />链表的难点在于必须复制链表处理函数来处理不同的对象，即便逻辑是完全相同的。例如两个结构类似的链表:<br /><br /><br /><center><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>struct Struct_Object_A
　　{
　　　　int a;
　　　　int b;
　　　　Struct_Object_A *next;
　　
　　} OBJECT_A;
　　
　　typedef struct Struct_Object_B
　　{
　　　　int a;
　　　　int b;
　　　　int c;
　　　　Struct_Object_B *next;
　　
　　} OBJECT_B;　</ccid_code></pre></td></tr></tbody></table></ccid_nobr></center><p style="TEXT-INDENT: 2em">上面定义的两个结构只有很小的一点差别。OBJECT_B 和 OBJECT_A 之间只差一个整型变量。但是，在编译器看来，它们仍然是非常不同的。必须为存储在链表中的每个对象复制用来添加、删除和搜索链表的函数。为了解决这个问题，可以使用具有全部三个变量的一个联合或结构，其中整数 c 并不是在所有的情况下都要使用。这可能变得非常复杂，并会形成不良的编程风格。 
</p><p style="TEXT-INDENT: 2em">C 代码解决方案：虚拟链表 
</p><p style="TEXT-INDENT: 2em">此问题更好的解决方案之一是虚拟链表。虚拟链表是只包含链表指针的链表。对象存储在链表结构背后。这一点是这样实现的，首先为链表节点分配内存，接着为对象分配内存，然后将这块内存分配给链表节点指针，如下所示： 
</p><p style="TEXT-INDENT: 2em">虚拟链表结构的一种实现 
</p><p style="TEXT-INDENT: 2em"></p><center><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>typedef struct liststruct
　　{
　　　　liststruct *next;
　　
　　} LIST, *pLIST;
　　
　　pLIST Head = NULL;
　　
　　pLIST AddToList( pLIST Head,
void * data, size_t datasize )
　　{
　　pLIST newlist=NULL;
　　void *p;
　　
　　　　// 分配节点内存和数据内存
　　　　newlist = (pLIST) malloc
( datasize + sizeof( LIST ) );
　　
　　　　// 为这块数据缓冲区指定一个指针
　　　　p = (void *)( newlist + 1 );
　　
　　　　// 复制数据
　　　　memcpy( p, data, datasize );
　　
　　　　// 将这个节点指定给链表的表头
　　　　if( Head )
　　　　{
　　　　newlist-&gt;next = Head;
　　　　}
　　　　else
　　　　newlist-&gt;next = NULL;
　　
　　　　Head = newlist;
　　
　　　　return Head;
　　}　　</ccid_code></pre></td></tr></tbody></table></ccid_nobr></center><p style="TEXT-INDENT: 2em">链表节点现在建立在数据值副本的基本之上。这个版本能很好地处理标量值，但不能处理带有用 malloc 或 new 分配的元素的对象。要处理这些对象，LIST 结构需要包含一个一般的解除函数指针，这个指针可用来在将节点从链表中删除并解除它之前释放内存（或者关闭文件，或者调用关闭方法）。 
</p><p style="TEXT-INDENT: 2em">一个带有解除函数的链表 
</p><p style="TEXT-INDENT: 2em"></p><center><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>typedef void (*ListNodeDestructor)( void * );
　　
　　typedef struct liststruct
　　{
　　　　ListNodeDestructor DestructFunc;
　　　　liststruct *next;
　　
　　} LIST, *pLIST;
　　
　　pLIST AddToList( pLIST Head, void * data, 
size_t datasize,
　　ListNodeDestructor Destructor )
　　{
　　pLIST newlist=NULL;
　　void *p;
　　
　　
　　　　// 分配节点内存和数据内存
　　　　newlist = (pLIST) malloc
( datasize + sizeof( LIST ) );
　　
　　　　// 为这块数据缓冲区指定一个指针
　　　　p = (void *)( newlist + 1 );
　　
　　　　// 复制数据
　　　　memcpy( p, data, datasize );
　　
　　　　newlist-&gt;DestructFunc = Destructor;
　　　　
　　　　// 将这个节点指定给链表的表头
　　　　if( Head )
　　　　{
　　　　　　newlist-&gt;next = Head;
　　　　}
　　　　else
　　　　　　newlist-&gt;next = NULL;
　　
　　　　Head = newlist;
　　
　　　　return Head;
　　}
　　
　　void DeleteList( pLIST Head )
　　{
　　　　pLIST Next;
　　　　while( Head )
　　　　{
　　　　　　Next = Head-&gt;next;
　　　　　　Head-&gt;DestructFunc( 
(void *) Head );
　　　　　　free( Head );
　　　　　　Head = Next;
　　　　}
　　}
　　
　　typedef struct ListDataStruct
　　{
　　　　LPSTR p;
　　
　　} LIST_DATA, *pLIST_DATA;
　　
　　void ListDataDestructor( void *p )
　　{
　　　　// 对节点指针进行类型转换
　　　　pLIST pl = (pLIST)p;
　　
　　　　// 对数据指针进行类型转换
　　　　pLIST_DATA pLD = (pLIST_DATA)
( pl + 1 );
　　
　　　　delete pLD-&gt;p;
　　}
　　pLIST Head = NULL;
　　
　　void TestList()
　　{
　　　　pLIST_DATA d = new LIST_DATA;
　　　　d-&gt;p = new char[24];
　　　　strcpy( d-&gt;p, "Hello" ); 
　　　　Head = AddToList( Head, (void *) d,
sizeof( pLIST_DATA ),
　　　　ListDataDestructor );
　　　　// 该对象已被复制，现在删除原来的对象
　　　　delete d;
　　
　　　　d = new LIST_DATA;
　　　　d-&gt;p = new char[24];
　　　　strcpy( d-&gt;p, "World" ); 
　　　　Head = AddToList( Head, (void *) d,
sizeof( pLIST_DATA ),
　　　　ListDataDestructor );
　　　　delete d;
　　
　　　　// 释放链表
　　　　DeleteList( Head );
　　}　　　</ccid_code></pre></td></tr></tbody></table></ccid_nobr></center><p style="TEXT-INDENT: 2em">在每个链表节点中包含同一个解除函数的同一个指针似乎是浪费内存空间。确实如此，但只有链表始终包含相同的对象才属于这种情况。按这种方式编写链表允许您将任何对象放在链表中的任何位置。大多数链表函数要求对象总是相同的类型或类。 
</p><p style="TEXT-INDENT: 2em">虚拟链表则无此要求。它所需要的只是将对象彼此区分开的一种方法。要实现这一点，您既可以检测解除函数指针的值，也可以在链表中所用的全部结构前添加一个类型值并对它进行检测。 
</p><p style="TEXT-INDENT: 2em">当然，如果要将链表编写为一个 C++ 类，则对指向解除函数的指针的设置和存储只能进行一次。 
</p><p style="TEXT-INDENT: 2em">C++ 解决方案：类链表 
</p><p style="TEXT-INDENT: 2em">本解决方案将 CList 类定义为从 LIST 结构导出的一个类，它通过存储解除函数的单个值来处理单个存储类型。请注意添加的 GetCurrentData() 函数，该函数完成从链表节点指针到数据偏移指针的数学转换。一个虚拟链表对象 
</p><p style="TEXT-INDENT: 2em"></p><center><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>// 定义解除函数指针
　　
　　typedef void (*ListNodeDestructor)
( void * );
　　
　　// 未添加解除函数指针的链表
　　
　　typedef struct ndliststruct
　　{
　　　　ndliststruct *next;
　　
　　} ND_LIST, *pND_LIST;
　　
　　// 定义处理一种数据类型的链表类
　　
　　class CList : public ND_LIST
　　{
　　public:
　　　　CList(ListNodeDestructor);
　　　　~CList();
　　　　pND_LIST AddToList
( void * data, size_t datasize );
　　　　void *GetCurrentData();
　　　　void DeleteList( pND_LIST Head );
　　
　　
　　private:
　　　　pND_LIST m_HeadOfList;
　　　　pND_LIST m_CurrentNode;
　　　　ListNodeDestructor
m_DestructFunc;
　　};
　　
　　// 用正确的起始值构造这个链表对象
　　
　　CList::CList(ListNodeDestructor Destructor)
　　　　: m_HeadOfList(NULL), 
m_CurrentNode(NULL)
　　{
　　　　m_DestructFunc = Destructor;
　　}
　　
　　// 在解除对象以后删除链表
　　
　　CList::~CList()
　　{
　　　　DeleteList(m_HeadOfList);
　　}
　　
　　// 向链表中添加一个新节点
　　
　　pND_LIST CList::AddToList
( void * data, size_t datasize )
　　{
　　pND_LIST newlist=NULL;
　　void *p;
　　
　　
　　　　// 分配节点内存和数据内存
　　　　newlist = (pND_LIST) malloc
( datasize + sizeof( ND_LIST ) );
　　
　　　　// 为这块数据缓冲区指定一个指针
　　　　p = (void *)( newlist + 1 );
　　
　　　　// 复制数据
　　　　memcpy( p, data, datasize );
　　
　　　　// 将这个节点指定给链表的表头
　　　　if( m_HeadOfList )
　　　　{
　　　　　　newlist-&gt;next = m_HeadOfList;
　　　　}
　　　　else
　　　　　　newlist-&gt;next = NULL;
　　
　　　　m_HeadOfList = newlist;
　　
　　　　return m_HeadOfList;
　　}
　　
　　// 将当前的节点数据作为 void 类型返回，
以便调用函数能够将它转换为任何类型
　　
　　void * CList::GetCurrentData()
　　{
　　　　return (void *)(m_CurrentNode+1);
　　}
　　
　　// 删除已分配的链表
　　
　　void CList::DeleteList( pND_LIST Head )
　　{
　　　　pND_LIST Next;
　　　　while( Head )
　　　　{
　　　　　　Next = Head-&gt;next;
　　　　　　m_DestructFunc( (void *) Head );
　　　　　　free( Head );
　　　　　　Head = Next;
　　　　}
　　}
　　
　　// 创建一个要在链表中创建和存储的结构
　　
　　typedef struct ListDataStruct
　　{
　　　　LPSTR p;
　　
　　} LIST_DATA, *pND_LIST_DATA;
　　
　　// 定义标准解除函数
　　
　　void ClassListDataDestructor( void *p )
　　{
　　　　// 对节点指针进行类型转换
　　　　pND_LIST pl = (pND_LIST)p;
　　
　　　　// 对数据指针进行类型转换
　　　　pND_LIST_DATA pLD = (pND_LIST_DATA)
( pl + 1 );
　　
　　　　delete pLD-&gt;p;
　　}
　　
　　// 测试上面的代码
　　
　　void MyCListClassTest()
　　{
　　　　// 创建链表类
　　
　　　　CList* pA_List_of_Data =
new CList(ClassListDataDestructor);
　　
　　　　// 创建数据对象
　　　　
　　　　pND_LIST_DATA d = new LIST_DATA;
　　　　d-&gt;p = new char[24];
　　　　strcpy( d-&gt;p, "Hello" ); 
　　
　　　　// 创建指向链表顶部的局部指针
　　
　　　　pND_LIST Head = NULL;
　　
　　　　//向链表中添加一些数据
　　
　　　　Head = pA_List_of_Data-&gt;AddToList
( (void *) d, 
　　　　sizeof( pND_LIST_DATA ) );
　　　　// 该对象已被复制，现在删除原来的对象
　　　　delete d;
　　
　　　　// 确认它已被存储
　　　　char * p = ((pND_LIST_DATA) pA_List_of_Data-&gt;GetCurrentData())-&gt;p;
　　
　　　　d = new LIST_DATA;
　　　　d-&gt;p = new char[24];
　　　　strcpy( d-&gt;p, "World" ); 
　　　　Head = pA_List_of_Data-&gt;AddToList
( (void *) d, sizeof( pND_LIST_DATA ) );
　　　　// 该对象已被复制，现在删除原来的对象
　　　　delete d;
　　
　　　　// 确认它已被存储
　　　　p = ((pND_LIST_DATA) 
pA_List_of_Data-&gt;GetCurrentData())-&gt;p;
　　
　　　　// 删除链表类，析构函数将删除链表
　　　　delete pA_List_of_Data;
　　}</ccid_code></pre></td></tr></tbody></table></ccid_nobr></center>　　 
<p style="TEXT-INDENT: 2em">小结 
</p><p style="TEXT-INDENT: 2em">从前面的讨论来看，似乎仅编写一个简单的链表就要做大量的工作，但这只须进行一次。很容易将这段代码扩充为一个处理排序、搜索以及各种其他任务的 C++ 类，并且这个类可以处理任何数据对象或类（在一个项目中，它处理大约二十个不同的对象）。您永远不必重新编写这段代码。</p><img src ="http://www.cppblog.com/zjj2816/aggbug/9034.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zjj2816/" target="_blank">井泉</a> 2006-06-26 19:37 <a href="http://www.cppblog.com/zjj2816/archive/2006/06/26/9034.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>队列</title><link>http://www.cppblog.com/zjj2816/archive/2006/06/26/9033.html</link><dc:creator>井泉</dc:creator><author>井泉</author><pubDate>Mon, 26 Jun 2006 11:25:00 GMT</pubDate><guid>http://www.cppblog.com/zjj2816/archive/2006/06/26/9033.html</guid><wfw:comment>http://www.cppblog.com/zjj2816/comments/9033.html</wfw:comment><comments>http://www.cppblog.com/zjj2816/archive/2006/06/26/9033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zjj2816/comments/commentRss/9033.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zjj2816/services/trackbacks/9033.html</trackback:ping><description><![CDATA[
		<p>
				<a name="8">
						<span class="atitle">
								<font face="Arial" size="4">队列</font>
						</span>
				</a>
		</p>
		<p>需要队列是出于两个原因。首先，需要队列来保存工作作业。还需要可用于跟踪已终止线程的数据结构。还记得前几篇文章（请参阅本文结尾处的 <a href="http://www-128.ibm.com/developerworks/cn/linux/thread/posix_thread3/index.html#resources"><font color="#996699">参考资料</font></a>）中，我曾提到过需要使用带有特定进程标识的 pthread_join 吗？使用“清除队列”（称作 "cq"）可以解决无法等待 <i>任何</i>已终止线程的问题（稍后将详细讨论这个问题）。以下是标准队列代码。将此代码保存到文件 queue.h 和 queue.c： </p>
		<br />
		<a name="N100F7">
				<b>queue.h</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">/* queue.h
** Copyright 2000 Daniel Robbins, Gentoo Technologies, Inc.
** Author: Daniel Robbins
** Date: 16 Jun 2000
*/

typedef struct node {
  struct node *next;
} node;

typedef struct queue {
  node *head, *tail; 
} queue;

void queue_init(queue *myroot);
void queue_put(queue *myroot, node *mynode);
node *queue_get(queue *myroot);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<br />
		<a name="N10103">
				<b>queue.c</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">/* queue.c
** Copyright 2000 Daniel Robbins, Gentoo Technologies, Inc.
** Author: Daniel Robbins
** Date: 16 Jun 2000
**
** This set of queue functions was originally thread-aware.  I
** redesigned the code to make this set of queue routines
** thread-ignorant (just a generic, boring yet very fast set of queue
** routines).  Why the change?  Because it makes more sense to have
** the thread support as an optional add-on.  Consider a situation
** where you want to add 5 nodes to the queue.  With the
** thread-enabled version, each call to queue_put() would
** automatically lock and unlock the queue mutex 5 times -- that's a
** lot of unnecessary overhead.  However, by moving the thread stuff
** out of the queue routines, the caller can lock the mutex once at
** the beginning, then insert 5 items, and then unlock at the end.
** Moving the lock/unlock code out of the queue functions allows for
** optimizations that aren't possible otherwise.  It also makes this
** code useful for non-threaded applications.
**
** We can easily thread-enable this data structure by using the
** data_control type defined in control.c and control.h.  */

#include &lt;stdio.h&gt;
#include "queue.h"

void queue_init(queue *myroot) {
  myroot-&gt;head=NULL;
  myroot-&gt;tail=NULL;
}

void queue_put(queue *myroot,node *mynode) {
  mynode-&gt;next=NULL;
  if (myroot-&gt;tail!=NULL)
    myroot-&gt;tail-&gt;next=mynode;
  myroot-&gt;tail=mynode;
  if (myroot-&gt;:head==NULL)
    myroot-&gt;head=mynode;
}

node *queue_get(queue *myroot) {
  //get from root
  node *mynode;
  mynode=myroot-&gt;head;
  if (myroot-&gt;head!=NULL)
    myroot-&gt;head=myroot-&gt;head-&gt;next;
  return mynode;
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/zjj2816/aggbug/9033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zjj2816/" target="_blank">井泉</a> 2006-06-26 19:25 <a href="http://www.cppblog.com/zjj2816/archive/2006/06/26/9033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>