c++双链表【构造函数、运算符重载、析构函数、增删查改及逆置等】

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)

建立头文件SList.h

#pragma once

typedef int DataType;
class ListNode
{
	friend class List;//友元函数
public:
	ListNode(const DataType x)
		:_data(x)
		, _prev(NULL)
		, _next(NULL)
	{}
private:
	DataType _data;
	ListNode* _prev;
	ListNode* _next;
};
class List
{
public:
	List()
		:_head(NULL)
		, _tail(NULL)
	{}
	//深拷贝
	List(const List& s)
		:_head(NULL)
		, _tail(NULL)
	{
		ListNode* tmp = s._head;
		while (tmp)
		{
			this->PushBack(tmp->_data);
			tmp = tmp->_next;
		}
	}
	//现代写法
	List& operator=(List& s)
	{
		swap(_head, s._head);
		swap(_tail, s._tail);
		return *this;
	}
public:
	void Clear();
	void PrintList();
	void PushBack(DataType x);
	void PopBack();
	void PushFront(DataType x);
	void PopFront();
	void Insert(ListNode* pos, DataType x);
	void Erase(ListNode* pos);
	ListNode* Find(DataType x);
	//void Reverse();
	List Reverse();
private:
	ListNode* _head;
	ListNode* _tail;
};

各函数的实现

#include<iostream>
using namespace std;

#include"List.h"
#include<assert.h>

void List::Clear()//清除双链表
{
	ListNode* cur = _head;
	while (cur)
	{
		ListNode* del = cur;
		cur = cur->_next;
		delete del;
		del = NULL;
	}
}

void List::PrintList()//打印双链表
{
	ListNode* cur=_head;
	while (cur)
	{
		cout << cur->_data << "->";
		cur = cur->_next;
	}
	cout << "NULL" << endl;
}

void List::PushBack(DataType x)//尾插
{
	if (NULL == _head)
	{
		_head = new ListNode(x);
		_tail = _head;
	}
	else
	{
		ListNode* tmp = new ListNode(x); 
		_tail->_next = tmp;
		tmp->_prev = _tail;
		tmp->_next = NULL;
		_tail = tmp;
	}
}

void List::PopBack()//尾删
{
	if (NULL == _head)
	{
		cout << "List is empty!" << endl;
	}
	else if (_head == _tail)
	{
		delete _head;
		_head = _tail = NULL;
	}
	else
	{//相比单链表方便找到尾节点的前一个节点
		ListNode* cur = _tail;
		_tail = cur->_prev;
		_tail->_next = NULL;
		delete cur;
		cur = NULL;
	}
}

void List::PushFront(DataType x)//头插
{
	ListNode* tmp = _head;
	_head = new ListNode(x);
	_head->_prev = NULL;
	_head->_next = tmp;
}

void List::PopFront()//头删
{
	if (NULL == _head)
	{
		cout << "SList is empty!" << endl;
	}
	else if (NULL == _head->_next)
	{
		delete _head;
		_head = NULL;
	}
	else
	{
		ListNode* tmp = _head->_next;
		delete _head;
		_head = tmp;
		tmp->_prev = NULL;
	}
}

ListNode* List::Find(DataType x)//查找x
{
	ListNode* cur = _head;
	while (cur)
	{
		if (x == cur->_data)
			return cur;
		cur = cur->_next;
	}
	return NULL;
}

void List::Insert(ListNode* pos, DataType x)//指定位置处插入x
{
	assert(pos);
	if (NULL == pos->_next)
		List::PushBack(x);
	else if (_head == pos)
		List::PushFront(x);
	else
	{
		ListNode* cur = new ListNode(x);
		ListNode* prev = pos->_prev;
		prev->_next = cur;
		cur->_prev = prev;
		cur->_next = pos;
		pos->_prev = cur;
	}
}

void List::Erase(ListNode* pos)//删除结点pos
{
	assert(pos);
	if (NULL == pos->_next)
		List::PopBack();
	else if (_head == pos)
		List::PopFront();
	else
	{
		ListNode* prev = pos->_prev;
		ListNode* next = pos->_next;
		next->_prev = prev;
		prev->_next = next;
	    delete pos;
		pos = NULL;
	}
}
//逆置双链表
//通过两个指针,从两边向中间移动,交换所储蓄内容
//void List::Reverse()
//{
//	ListNode* begin = _head;
//	ListNode* end = _tail;
//	//奇数个节点时两个指针相等时结束循环;偶数个节点时两个指针发生交叉时结束循环
//	while (begin != end && begin->_prev != end)
//	{
//		swap(begin->_data, end->_data);
//		begin = begin->_next;
//		end = end->_prev;
//	}
//}

//交换头尾指针,交换每个结点的前驱和后继
//void List::Reverse()
//{
//	swap(_head, _tail);
//	ListNode* cur = _head;
//	while (cur)
//	{
//		swap(cur->_prev,cur->_next);
//		cur = cur->_next;
//	}
//}

//建立新链表,通过头插法实现
List List::Reverse()
{
	if (NULL == _head)
	{
		cout << "SList is empty!" << endl;
	}
	else if(NULL != _head->_next)
	{
		List NewList;
		ListNode* cur = _head->_next;
		ListNode* tmp = _head;//保存头指针,头插完后使其_next指针指向空
		while (cur)
		{
			this->PushFront(cur->_data);
			cur = cur->_next;
		}
		tmp->_next = NULL;
		return NewList;
	}
	return *this;
}

本文出自 “Scen” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1748592

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值