原书这部分内容很多,至少相对于循环链表是很多。相信当你把单链表的指针域搞清楚后,这部分应该难不倒你。现在我的问题是,能不能从单链表派生出双向链表?<?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 putprior(node<type> *p)//尽量不用,原因同上 |
因为这个接口很危险,而且几乎用不到,所以我在前面并没有给出,但要完成双向链表最\"杰出\"的优点——向前移动当前指针,必须要使用。另外说的是,我从前也从来没计划从单链表派生双链表,下面你将看到,这个过程很让人烦人,甚至不如重写一个来的省事,执行效率也不是很好,这种费力不讨好的事做它有什么意思呢?的确,我也觉得我在钻牛角尖。
定义和实现
#ifndef dbllist_h #include \"list.h\" template <class type> class dbllist : public list< node<type> > type *next() type *prior() void insert(const type &value) bool remove() }; #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; } |