# 第33课 - 双向循环链表的实现

1、双向循环链表的实现

课程目标

- 使用Linux内核链表实现DTLib中的双向循环链表

- template < typename T > class DualCircleList

DTLib中双向循环链表的设计思路

数据结点之间在逻辑上构成双向循环

链表，头结点仅用于结点的定位。

－在DualCircleList内部使用Linux内核链表进行实现

－特殊处理：循环遍历时忽略头结点

－通过list_for_each实现int find(const T& e)函数

－遍历函数中的 next() pre() 需要考虑跳过头结点

2、编程实验

#ifndef DUALCIRCLELIST_H
#define DUALCIRCLELIST_H

#include "LinuxList.h"

namespace DTLib
{

template <typename T>
{
protected:
struct Node : public Object
{
T value;
};

{

for(int p=0;p<i;p++)
{
ret = ret->next;
}

return ret;
}

int mod(int i) const
{

return (this->m_length == 0) ? 0 : (i % this->m_length);
}
public:
DualCircleList()
{
this->m_length = 0;
this->m_step = 1;

m_current = NULL;

}

bool insert(const T& e)
{
return insert(this->m_length,e);
}
bool insert(int i,const T& e)
{
bool ret = true;
Node* node = new Node();

i = i % (this->m_length + 1);

if(node)
{
node->value = e;

this->m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create a new element ...");
}

return ret;
}

bool remove(int i)
{
bool ret = true;

i = mod(i);

ret = (0 <= i) && (i < this->m_length);

if(ret)
{

if(m_current == toDel)
{
m_current = toDel->next;
}

list_del(toDel);

this->m_length--;

}

return ret;
}

bool set(int i,const T& e)
{
bool ret = true;

i = mod(i);

ret = (0 <= i) && (i < this->m_length);

if(ret)
{
}

return ret;
}
T get(int i) const
{
T ret;

if(get(i,ret))
{
return ret;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsExpception,"Invalid parameter i to get element ...");
}

return ret;
}
bool get(int i,T& e) const
{
bool ret = true;

i = mod(i);

ret = (0 <= i) && (i < this->m_length);

if(ret)
{
}

return ret;
}
int find(const T& e) const
{
int ret = -1;
int i =0;

{
{
ret = i;
break;
}

i++;
}

return ret;
}

int length() const
{
return this->m_length;
}
void clear()
{
while(this->m_length > 0)
{
remove(0);
}
}

bool move(int i, int step=1)
{
bool ret = (step > 0);

i = mod(i);

ret = ret && (0 <= i) && (i < this->m_length);

if(ret)
{
m_current = position(i)->next;
this->m_step = step;
}

return ret;
}
bool end()
{
return ( m_current == NULL)||(this->m_length == 0);
}
T current()
{
if(!end())
{
}
else
{
THROW_EXCEPTION(InvalidParameterException,"No value at current position ...");
}
}
bool next()
{
int i = 0;
while((i < this->m_step) && !end())
{
{
m_current = m_current->next;
i++;
}
else
{
m_current = m_current->next;
}
{
m_current = m_current->next;
}
}

return (i == this->m_step);
}
bool pre()
{
int i = 0;
while((i < this->m_step) && !end())
{
{
m_current = m_current->prev;
i++;
}
else
{
m_current = m_current->prev;
}
{
m_current = m_current->prev;
}
}

return (i == this->m_step);
}
~DualCircleList()
{
clear();
}

};
}

#endif // DUALCIRCLELIST_H


main.cpp

#include <iostream>
#include "DualCircleList.h"

using namespace std;
using namespace DTLib;

int main()
{
DualCircleList<int> d1;

for(int i=0; i<5; i++)
{
d1.insert(0, i);
d1.insert(0, 5);
}

for(int i=0; i<d1.length(); i++)
{
cout << d1.get(i) << " ";
}
cout << endl;

d1.move(d1.length()-1);

while(d1.find(5) != -1)
{
if(d1.current() == 5)
{
cout << d1.current() << " ";
d1.remove(d1.find(d1.current()));
}
else
{
d1.pre();
}
}

cout<<endl;
for(int i=0; i<10; i++)
{
cout << d1.get(i) << " ";
}
cout << endl;

int i =0;
for(d1.move(d1.length()-1); (i<d1.length())&&(!d1.end()); d1.pre(),i++)
{
cout << d1.current() << " ";
}

return 0;
}



3、小结

Linux内核链表是带头结点的双向循环链表

DualCircleList使用Linux内核链表进行内部实现

DualCircleList在循环遍历时需要跳过头结点

4、思考题

下面代码中的pn1和pn2是否相等？为什么？

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120