选择显示字体大小

数据结构学习(c++)之双向链表


  原书这部分内容很多,至少相对于循环链表是很多。相信当你把单链表的指针域搞清楚后,这部分应该难不倒你。现在我的问题是,能不能从单链表派生出双向链表?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
你可以有几种做法:



  一种就是先定义一个双链节点--但是,它的名字必须叫node,这是没办法的事;不然你就只好拷贝一份单链表的实现文件,把其中的node全都替换成你的双链节点名字,但是这就不叫继承了。
另一种做法就是先定义一种结构例如这样的:

template <class type> class newtype
{
public:
type data;
node<newtype> *link;
}

  当你派生双向链表时,这样写template <calss type> class dbllist : public list<newtype<type> >,注意连续的两个">"之间要有空格。或者根本不定义这样的结构,直接拿node类型来做,例如我下面给出的。但是,请注意要完成"=="的重载,否则,你又要重写find函数,并且其他的某些操作也不方便。

  在开始完成你的从单链表派生出来的双向链表之前,要在单链表这个基类中添加修改当前指针和当前前驱指针的接口,如下所示:

protected:
void put(node<type> *p)//尽量不用,双向链表将使用这个完成向前移动
{
current = p;
}

void putprior(node<type> *p)//尽量不用,原因同上
{
prior = p;
}

  因为这个接口很危险,而且几乎用不到,所以我在前面并没有给出,但要完成双向链表最"杰出"的优点--向前移动当前指针,必须要使用。另外说的是,我从前也从来没计划从单链表派生双链表,下面你将看到,这个过程很让人烦人,甚至不如重写一个来的省事,执行效率也不是很好,这种费力不讨好的事做它有什么意思呢?的确,我也觉得我在钻牛角尖。

  定义和实现

#ifndef dbllist_h
#define dbllist_h

#include "list.h"

template <class type> class dbllist : public list< node<type> >
{
public:
type *get()
{
if (pget() != null) return &pget()->data.data;
else return null;
}

type *next()
{
pnext();
return get();
}

type *prior()
{
if (pgetprior != null)
{
put(pgetprior());
putprior( (node< node<type> >*)pget()->data.link);
return get();
}
return null;
}

void insert(const type &value)
{
node<type> newdata(value, (node<type>*)pget());
list< node<type> >::insert(newdata);
if (pgetnext()->link != null)
pgetnext()->link->data.link = (node<type>*)pgetnext();
}

bool remove()
{
if (list< node<type> >::remove())
{
pget()->data.link = (node<type>*)pgetprior();
return ture;
}
return false;
}

};

#endif

  【说明】只完成了最重要的insert和remove函数和最具特点的prior()函数,其他的没有重新实现。所以,你在这里使用单链表的其他方法,我不保证一定正确。并且,这里的指针类型转换依赖于编译器实现,我也不能肯定其他的编译器编译出来也能正确。对于让不让prior返回头节点的data,我考虑再三,反正用first();get();这样的组合也能返回,所以就不在乎他了,所以要是用prior遍历直到返回null,就会将头节点的data输出来了。

  【补充】至于双向循环链表,也可以从这个双向链表派生(仿照派生循环链表的方法);或者从循环链表派生(仿照派生双向链表的方法),就不一一举例了(再这样下去,我就真闹心的要吐血了)。至此,可以得出一个结论,链表的各种结构都是能从单链表派生出来的。换句话说,单链表是根本所在,如果研究透了单链表,各种链式结构都不难。

  一小段测试程序

void dbllisttest_int()
{
dbllist<int> a;
for (int i = 10; i > 1; i--) a.insert(i);
for (i = 10; i > 1; i--) cout << *a.next() << " ";
a.first();
cout << endl;
cout << *a.next() << endl;
cout << *a.next() << endl;
cout << *a.next() << endl;
cout << *a.next() << endl;
a.remove();
cout << *a.get() << endl;
cout << *a.prior() << endl;
cout << *a.prior() << endl;
cout << *a.prior() << endl;
}

  【后记】从我对双向链表不负责任的实现来看,我并不想这么来实现双向链表,我只是尝试怎样最大限度的利用已有的类来实现这种类型。实践证明,不如重写一个。别人看起来也好看一些,自己写起来也不用这样闹心。不过,这个过程让我对函数的调用和返回的理解又更深了一步。如果你能第一次就写对这里的insert函数,相信你一定对c++有一定的感触了。我也觉得,只有做一些创新,才能最已经很成熟的东西更深入的了解。比如,这些数据结构,在c++的标准库(stl)中都可以直接拿来用,我们为什么还辛辛苦苦的写,结果还不如人家原来的好。为了学习,这就是理由,这也是一切看起来很笨的事发生的理由。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons