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

数据结构与算法分析(c++版) #6 双链表

2015-09-18 19:20 344 查看
双链表
单链表只允许从一个表结点直接访问它的后继结点,而双链表可以从一个表结点出发,在线性表中随意访问它的前驱结点和后继接电脑。双链表存储两个指针,使这些成为可能:一个智指向它的后继结点(与单链表相同),另一个指向它的前驱结点。如下图:



下面是双链表的结点类实现:
template <class Elem> class Node
{
private:
	static Node<Elem>* freelist;	// 空闲表
public:
	Elem element;		// 该结点的值
	Node* next;		// 指向下一个结点
	Node* prev;
	//	两个构造函数 
	Node(const Elem& elemval, Node* preval = nullptr, Node* nextval = nullptr)
	{
		element = elemval; prev = preval; next = nextval;
	}
	Node(Node* preval = nullptr, Node* nextval = nullptr) { prev = preval; next = nextval; }
	// 重载操作符
	void* operator new(size_t);
	void operator delete(void*);
};

template <class Elem>
Node<Elem>* Node<Elem>::freelist = nullptr;

template <class Elem>
void* Node<Elem>::operator new(size_t)
{
	//	如果空闲表为空,调用系统的new创建一个Node对象
	if (freelist == nullptr) return ::new Node;
	Node<Elem>* temp = freelist;
	freelist = freelist->next;
	return temp;
}

template <class Elem>
void Node<Elem>::operator delete(void* ptr)
{
	((Node<Elem>*)ptr)->next = freelist;
	freelist = (Node<Elem>*)ptr;
}


而对于链表类的实现,只需改变insert,append,remove,prev函数即可:
//	在右表最前面插入元素
template <class Elem>
bool DLList<Elem>::insert(const Elem& item)
{
	// 在栅栏后插入新结点,把新结点的next指向栅栏后一个结点,prev指向栅栏,再把本身的地址附给栅栏后面 
	fence->next = new Node<Elem>(item, fence, fence->next);
	// 如果新结点不是最后一个结点,就把后一个结点的prev指向新结点
	if (fence->next->next != nullptr)
		fence->next->next->prev = fence->next;
	if (tail == fence)
		tail = fence->next;
	++rightcnt;
	return true;
}

//	在右表末尾拼接元素
template <class Elem>
bool DLList<Elem>::append(const Elem& item)
{
	tail = tail->next = new Node<Elem>(item, tail, nullptr);
	++rightcnt;
	return true;
}

//	删除右表第一个元素
template <class Elem>
bool DLList<Elem>::remove(Elem& item)
{
	// 右表为空 
	if (fence->next == nullptr)
		return false;
	// 读出要删除的值
	item = fence->next->element;
	// 创建临时结点
	Node<Elem>* ntemp = fence->next;
	// 如果右表只剩下最后一个元素
	if (ntemp->next != nullptr)
		ntemp->next->prev = fence;
	else tail = fence;
	fence->next = ntemp->next;
	delete ntemp;
	--rightcnt;
	return true;
}

//  把栅栏的位置向左移动一个单位,如果栅栏已经是表头就不移动
template <class Elem>
void DLList<Elem>::prev()
{
	if (fence != head)
	{
		fence = fence->prev;
		--leftcnt;
		++rightcnt;
	}
}
双链表与单链表相比唯一的缺点就是使用更多的空间需求。双链表的每一个结点需要两个指针。这种实现方法,它需要的结构性开销是单链表的两倍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: