c++中的雙向鏈表寫法,主要實現(增刪查改,鏈表逆置,構造函數,運算符重載,等)

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;
}

    以上函數均是在學習的過程中總結寫出的,肯定會有一些疏漏或者錯誤之處,所以敬請各位大神的批評指正,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章