您的位置:首页 > 理论基础 > 数据结构算法

数据结构基础(12) --双向循环链表的设计与实现

2015-01-06 19:19 1241 查看
双向链表的操作特点:
    (1) “查询” 和单链表相同;
    (2)“插入” 和“删除”时需要同时修改两个方向上的指针。
   但是对于双向循环链表则在表尾插入非常的迅速, 只需O(1)的时间,因为有指向前面的指针, 因此双向循环链表会很容易的找到位于表尾的元素,因此双向循环链表比较适用于频繁在表尾插入的情况.



空链表:



双向循环链表节点构造:
class DoubleListNode
{
private:
Type data;
DoubleListNode *prev; //前向指针域
DoubleListNode *next; //后项指针域
};
因为需要将其用于DoubleList类,因此需要将其改造如下:template <typename Type>
class DoubleListNode
{
//友元声明
friend class DoubleList<Type>;
friend class ListIterator<Type>;

template <typename T>
friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
private:
DoubleListNode(const Type &dataValue)
:data(dataValue),prev(NULL),next(NULL) {}

Type data;
DoubleListNode *prev; //前向指针域
DoubleListNode *next; //后项指针域
};
双向循环链表构造:template <typename Type>
class DoubleList
{
friend class ListIterator<Type>;
template <typename T>
friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
public:
DoubleList();
~DoubleList();

void push_back(const Type &data);
void push_front(const Type &data);
void insert(int position, const Type &data);

void pop_front();
void pop_back();
void remove(const Type &removeData);

bool search(const Type &searchData) const;
bool isEmpty() const
{
return (first->next == first);
}

private:
//将节点x插入到节点previous后面
void insertPrivate(DoubleListNode<Type> *previous,
DoubleListNode<Type> *x);
void removePrivate(DoubleListNode<Type> *x);

private:
DoubleListNode<Type> *first;
};
链表的构造与析构://构造链表
template <typename Type>
DoubleList<Type>::DoubleList()
{
first = new DoubleListNode<Type>(0);
first->next = first;
first->prev = first;
}
//析构链表
template <typename Type>
DoubleList<Type>::~DoubleList()
{
DoubleListNode<Type> *deleteNode = NULL;
//保存链表尾元素
DoubleListNode<Type> *tmp = first;

//first首先指向第一个真实的元素
first = first->next;
//一路到达链表结尾
while (first != tmp)
{
deleteNode = first;
first = first -> next;
delete deleteNode;
}
// 释放掉链表的空节点(表头)
delete tmp;
}

链表元素插入与删除的两大主力://同为private成员
//插入节点
template <typename Type>
void DoubleList<Type>::insertPrivate(DoubleListNode<Type> *previous,
DoubleListNode<Type> *x)
{
x->prev = previous;
x->next = previous->next;
previous->next->prev = x;
previous->next = x;
}
//删除节点
template <typename Type>
void DoubleList<Type>::removePrivate(DoubleListNode<Type> *x)

{
if (x == first)
throw std::range_error("permission denied to delete first pointer");

x->prev->next = x->next;
x->next->prev = x->prev;
delete x;
}

提供给客户的插入://插入到表尾
template <typename Type>
void DoubleList<Type>::push_back(const Type &data)
{
DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
//找到first的前一个节点
DoubleListNode<Type> *previous = first->prev;

//插入
insertPrivate(previous, newNode);
}
//插入到表头
template <typename Type>
void DoubleList<Type>::push_front(const Type &data)
{
DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
//插入到first之后
insertPrivate(first, newNode);
}

//插入到任意位置(依position指定)
template <typename Type>
void DoubleList<Type>::insert(int position, const Type &data)
{
if (position == 1)
return push_front(data);

int count = 1;
//previous 代表着要插入位置之前的一个位置
DoubleListNode<Type> *previous = first->next;

//如果position过大, 则previous查找到first就会停止
//此时应该将该元素插入到链表结尾
while (count < position-1 && previous != first)
{
++ count;
previous = previous->next;
}

//如果查找到了链表结尾或此时链表为空, 因此插入到表尾
if (previous == first)
return push_back(data);

//如果找到了合适的插入位置
DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
insertPrivate(previous, newNode);
}
提供给客户的删除://删除表尾元素
template <typename Type>
void DoubleList<Type>::pop_back()
{
removePrivate(first->prev);
}
//删除表头元素
template <typename Type>
void DoubleList<Type>::pop_front()
{
removePrivate(first->next);
}

//删除元素值为removeData的所有元素
template <typename Type>
void DoubleList<Type>::remove(const Type &removeData)
{
if (isEmpty())
throw std::range_error("link list is empty");

for( DoubleListNode<Type> *searchNode = first->next;
searchNode != first;
searchNode = searchNode->next)
{
if (searchNode->data == removeData)
removePrivate(searchNode);
}
}
查看是否存在于链表中:template <typename Type>
bool DoubleList<Type>::search(const Type &searchData) const
{
DoubleListNode<Type> *searchNode = first->next;
while (searchNode != first)
{
if (searchNode->data == searchData)
return true;

searchNode = searchNode->next;
}
return false;
}
输出链表所有元素(测试用):template <typename Type>
ostream &operator<<(ostream &os, const DoubleList<Type> &list)
{
for (DoubleListNode<Type> *currentNode = (list.first)->next;
currentNode != list.first;
currentNode = currentNode->next)
os << currentNode->data << ' ';

return os;
}

双向循环链表迭代器的设计与实现:

//除了添加了operator--, 几乎没做任何改变
template <typename Type>
class ListIterator
{
public:
ListIterator(const DoubleList<Type> &_list):
list(_list),
currentNode((_list.first)->next) {}

//重载 *operator
const Type &operator*() const throw (std::out_of_range);
Type &operator*() throw (std::out_of_range);

//重载 ->operator
const DoubleListNode<Type> *operator->() const throw (std::out_of_range);
DoubleListNode<Type> *operator->() throw (std::out_of_range);

//重载 ++operator
ListIterator &operator++() throw (std::out_of_range);
//注意:此处返回的是值,而不是reference
ListIterator operator++(int) throw (std::out_of_range);

//重载 --operator,
// 其实这个版本的--operator是不完美的,
// 因为他没有做任何的判错控制
ListIterator &operator--();
//注意:此处返回的是值,而不是reference
ListIterator operator--(int);

bool isEmpty() const
{
return (currentNode == list.first);
}

private:
const DoubleList<Type> &list;
DoubleListNode<Type> *currentNode;
};
template <typename Type>
const Type &ListIterator<Type>::operator*() const
throw (std::out_of_range)
{
if (isEmpty())
throw std::out_of_range("iterator is out of range");
// 返回当前指针指向的内容
return currentNode->data;
}
template <typename Type>
Type &ListIterator<Type>::operator*()
throw (std::out_of_range)
{
return
const_cast<Type &>(
static_cast<const ListIterator<Type> &>(*this).operator*()
);
}
template <typename Type>
const DoubleListNode<Type> *ListIterator<Type>::operator->() const
throw (std::out_of_range)
{
if (isEmpty())
throw std::out_of_range("iterator is out of range");

//直接返回指针
return currentNode;
}

template <typename Type>
DoubleListNode<Type> *ListIterator<Type>::operator->()
throw (std::out_of_range)
{
return
const_cast<DoubleListNode<Type> *> (
static_cast<const ListIterator<Type> >(*this).operator->()
);
}
template <typename Type>
ListIterator<Type> &ListIterator<Type>::operator++()
throw (std::out_of_range)
{
if (isEmpty())
throw std::out_of_range("iterator is out of range");
//指针前移
currentNode = currentNode->next;
return *this;
}
template <typename Type>
ListIterator<Type> ListIterator<Type>::operator++(int)
throw (std::out_of_range)
{
ListIterator tmp(*this);
++ (*this); //调用前向++版本

return tmp;
}
template <typename Type>
ListIterator<Type> &ListIterator<Type>::operator--()
{
//指针前移
currentNode = currentNode->prev;
return *this;
}
template <typename Type>
ListIterator<Type> ListIterator<Type>::operator--(int)
{
ListIterator<Type> tmp(*this);
-- (*this);

return tmp;
}

测试代码:int main()
{
cout << "-------- 1 --------" << endl;
DoubleList<int> myList;

for (int i = 0; i < 3; ++i)
myList.push_back(i+1);
for (int i = 0; i < 5; ++i)
myList.push_front(10+i);
for (int i = 0; i < 3; ++i)
myList.push_back(i+1);

ListIterator<int> iter(myList), iter2(myList);
while (!iter.isEmpty())
{
cout << *iter << ' ';
++ iter;

++ iter2;
}
cout << endl;

-- iter2;
while (!iter2.isEmpty())
{
cout << *iter2 << ' ';
iter2 --;
}
cout << endl;

cout << "-------- 2 --------" << endl;

cout << myList << endl;
cout << "Test insert..." << endl;
myList.insert(1, 14);
myList.insert(2, 13);
myList.insert(2, 13);
myList.insert(88, 88);
cout << myList << endl;

myList.pop_back();
myList.pop_front();
cout << myList << endl;

for (int i = 0; i < 5; ++i)
{
if (myList.search(i))
cout << i << ": Have found!" << endl;
else
cout << i << ": Not in the list!" << endl;
}

cout << "Test remove..." << endl;
cout << myList << endl;
int value;
while (cin >> value)
{
try
{
myList.remove(value);
}
catch (const std::exception &e)
{
cerr << e.what() << endl;
}

cout << myList << endl;
if (myList.isEmpty())
{
cout << "empty" << endl;
}
else
{
cout << "not empty" << endl;
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息