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

本文主要内容

1)介绍c++中双向链表的写法。

2)实现双向链表中数据的增、删、查、改、链表逆置、链表输出

3)介绍类中构造函数、析构函数、运算符重载函数的写法


接下来介绍双向链表的成员函数:这写函数放在头文件中,方便编写

#pragma once

#include<iostream>
using namespace std;
#include<assert.h>

typedef int DataType;

class ListNode  //节点
{
public:
	ListNode(DataType x)
		:_data(x),
		_next(NULL),
		_prev(NULL)
	{}

	ListNode*_next;
	ListNode*_prev;
	DataType _data;
};

class List  //双向链表
{
public:
	List();
	List(List&s);
	List&operator=(const List&s);
	~List();

	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();
	void PrintList();
	void Clear();
	void PrintReverseList();

private:
	ListNode*_head;
	ListNode* _tail;
};


接下来介绍各个函数,

1)构造函数(此处写了一种,因为只用到了这一种)

List::List()
		:_head(NULL),
		_tail(NULL)
	{}

2)构造函数中的拷贝构造

List::List(List&s)
:_head(NULL),
_tail(NULL)
{
	ListNode*cur = s._head;
	while (cur)
	{
		PushBack(cur->_data);
		cur = cur->_next;
	}
}

3)赋值运算符重载

List& List::operator=(const List&s)
{
	_head = NULL;
	_tail = NULL;
	ListNode*cur = s._head;
	while (cur)
	{
		PushBack(cur->_data);
		cur = cur->_next;
	}
	return *this;
}

4)析构函数

List::~List()
{
	Clear();
}

void List::Clear()
{
	cout << "~Clear()  ";
	ListNode*cur = _head;
	while (cur)
	{
		ListNode*del = cur;
		cur = cur->_next;
		delete del;
	}
	cout << " clear  is   NULL" << endl;
}

5)增加节点的函数(三种,前增、后增、给定节点后插入)

void List::PushFront(DataType x)
{
	if (_head == NULL)
	{
		_head = new ListNode(x);
		_tail = _head;
	}
	else
	{
		ListNode*temp = new ListNode(x);
		_head->_prev = temp;
		temp->_next = _head;
		_head = temp;
	}
}

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

void List::Insert(ListNode *pos, DataType x)
{
	assert(pos);
	if (pos == _tail)
	{
		PushBack(x);
	}
	else
	{
		ListNode*cur = pos->_next;
		ListNode*temp = new ListNode(x);
		temp->_next = cur;
		temp->_prev = pos;
		pos->_next = temp;
		cur->_prev = temp;
	}
}

6)删除节点(三种,前删、后删、删除给定节点)

void List::PopFront()
{
	if (_head == NULL)
	{
		cout << "空链表!" << endl;
		return;
	}
	else
	{
		if (_head->_next)
		{
			ListNode *temp = _head;
			_head = _head->_next;
			_head->_prev = NULL;
			delete temp;
		}
		else
		{
			delete _head;
			_head = _tail = NULL;
		}
	}
}

void List::PopBack()
{
	if (_head == NULL)
	{
		cout << "空链表!" << endl;
		return;
	}
	else
	{
		if (_tail->_prev)
		{
			ListNode *temp = _tail;
			_tail = _tail->_prev;
			_tail->_next = NULL;
			delete temp;
		}
		else
		{
			delete _tail;
			_head = _tail = NULL;
		}
	}
}

void List::Erase(ListNode*pos)
{
	assert(pos);
	if (pos == _head)
	{
		PopFront();
	}
	else if (pos == _tail)
	{
		PopBack();
	}
	else
	{
		ListNode*temp = pos->_prev;
		ListNode*next = pos->_next;
		temp->_next = next;
		next->_prev = temp;
		delete pos;
	}
}

7)寻找节点

ListNode* List::Find(DataType x)
{
	if (_head == NULL)
	{
		cout << "空链表!" << endl;
		return  NULL;
	}
	ListNode*cur = _head;
	while (cur)
	{
		if (cur->_data == x)
			return cur;
		cur = cur->_next;
	}
}

8)双向链表逆置(两种方法)

方法一:交换每个节点的前驱和后继。

方法二:创建新的链表,从远链表上摘节点然后补到新链表上

//void List::Reverse()   //方法 一
//{
//	if (_head == NULL)
//	{
//		cout << "空链表!" << endl;
//		return;
//	}
//	else if (_head == _tail)
//		return;
//	else
//	{
//		swap(_tail,_head);
//		ListNode *cur = _head;
//		while (cur)
//		{
//			swap(cur->_prev, cur->_next);
//			cur = cur->_next;
//		}
//	}
//}

void List::Reverse()//方法二
{
	if (_head == NULL)
	{
		cout << "空链表!" << endl;
		return;
	}
	else if (_head == _tail)
		return;
	else
	{

		ListNode*cur = _tail;
		ListNode *newhead = NULL;
		while (cur)
		{
			if (newhead == NULL)
			{
				newhead = new ListNode(cur->_data);
				_head = newhead;
			}
			else
			{
				ListNode*temp = new ListNode(cur->_data);
				newhead->_next = temp;
				temp->_prev = newhead;
				newhead = temp;
				_tail = temp;
			}
			ListNode* del = cur;
			cur = cur->_prev;
			delete del;
		}
	}
}

9)打印链表(两种,顺序打印、逆序打印)

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

void List::PrintReverseList()//逆序打印
{
	cout << "从后向前:";
	ListNode*cur = _tail;
	while (cur)
	{
		cout << cur->_data << "->";
		cur = cur->_prev;
	}
	cout << "NULL" << endl;
}


当然还有主函数(测试用例)

#include"List.h"
void Test3()
{
	cout << endl;
	List l1;
	l1.PushFront(1);
	l1.PushBack(2);
	l1.PushBack(3);
	l1.PushBack(4);
	l1.PushBack(5);
	l1.PushBack(6);


	//l1.PushFront(4);
	//l1.PopFront();//前删
	//l1.PopBack();//后删

	//ListNode *pos = l1.Find(3);
	//l1.Insert(pos, 5);

	//l1.Erase(pos);
	cout << "l1 :";
	l1.PrintList();
	l1.PrintReverseList();
	cout << "逆置l1 :";
	l1.Reverse();
	l1.PrintList();
	l1.PrintReverseList();
	cout << "拷贝构造-》 l2 :";
	List l2(l1);
	l2.PrintList();

	cout << "赋值运算符重载 -》 l3 :";
	List l3;
	l3 = l2;
	l3.PrintList();
}

int main()
{
	Test3();
	system("pause");
	return 0;
}

    以上函数均是在学习的过程中总结写出的,肯定会有一些疏漏或者错误之处,所以敬请各位大神的批评指正,谢谢