数据结构之链表

本文围绕数据结构中的链表展开,介绍了链表的存储结点由数据域和指针域构成。详细阐述了单链表、循环链表和双向链表的基本思想、算法思路,如单链表插入和删除操作只需改“链”,还给出了三种链表各操作的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表

数据结构中的每个节点都对应一个存储单位,这种存储单元称之为存储结点。结点有两个部分组成,一是数据域,用来存储数据;二是指针域,用来存放指向前一个或者后一个结点的指针。链表按照连接的方式分为三种,分别是单链表、循环链表、双向链表。

1、单链表

基本思想指向单链表的第一个结点的指针,用head表示,称为头指针;data表示数据域,next表示指针域;尾结点的指针域为NULL,并且当头指针为NULL时,表示链表是一个空表。

算法思路:单链表主要的功能是对表的插入和删除,因为单链表有指针域的存在,对于插入和删除操作来说只需要修改“链”就能实现,不需要像数组那样要移动数据。

1、单链表的头插

单链表的头插只需要将待插入的结点的指针域指向头节点的下一个结点,并将头节点的指针域指向待插入的结点就完成了。

(1)

(2)

(3)

2、单链表的尾插

(1)

(2)

(3)

3、单链表的删除

(1)

(2)

(3)

 

代码实现:

单链表的结构

//单链表
class SimpleList
{
public:
	SimpleList(){}    //构造函数
	~SimpleList(){}   //析构函数
	void InsertHead(int val);    //头插
	void InsertTail(int val);    //尾插
	void Remove(int val);        //删除
	bool FindValue(int val);     //查找
	bool Empty();                //判空
	int Front();                 //获取头元素
	void DeleteFront();          //删除头元素
	void Show();                 //打印数据
private:
	class Node
	{
	public:
		Node(int data = 0) :_data(data), _next(nullptr) {}
	private:
		int _data;
		Node* _next;
		friend class SimpleList;
	};
	Node* _head;
};

1、单链表的头插

void InsertHead(int val)
	{
		Node *tmp = new Node(val);
		tmp->_next = _head->_next;
		_head->_next = tmp;
	}

2、单链表的尾插

void InsertTail(int val)
	{
		Node *tail = _head;
		while (tail->_next != nullptr)
		{
			tail = tail->_next;
		}
		tail->_next = new Node(val);
	}

3、单链表的删除

Node *tmp = _head;
		Node *del = _head->_next;
		while (del != nullptr)
		{
			if (del->_data == val)
			{
				tmp->_next = del->_next;
				delete del;
				del = tmp->_next;
			}
			tmp = del;
			del = del->_next;
		}

2、循环链表

基本思想:循环链表和单链表相似,但是循环链表尾结点的指针域保存的是头节点的指针。

算法思路:带头结点的循环链表的操作与单链表相似,只是遍历链表的算法只要将单链表中的判断终止条件由NULL该为head就可以了,但需要注意的是循环链表的删除。

循环链表的删除:

(1)

(2)

 

代码实现:

循环链表的结构

class CircleList
{
public:
	CircleList()        //构造函数
	{
		_head = new Node();
		_head->_next = _head;
	}
	~CircleList()       //析构函数
	{
		Node* tmp = _head;
		Node* tail = _head->_next;
		while (tail != _head)
		{
			tail = tail->_next;
		}
		while (tmp != tail)
		{
			_head = _head->_next;
			delete tmp;
			tmp = _head;
		}
                delete _head;
	}
	void InsertHead(int val);    //头插
	void InsertTail(int val);    //尾插
	void Remove(int val);        //删除指定值
	bool FindValue(int val);     //查找
	bool Empty();                //判空
	int Front();                 //获取头结点
	void DeleteFront();          //删除头节点
	void Show();                 //展示
private:
	class Node
	{
	public:
		Node(int data = 0) :_data(data) {}
	private:
		int _data;
		Node* _next;
		friend class CircleList;
	};
	Node* _head;
}

循环链表的删除

void Remove(int val)
{
	Node *tmp = _head;
	Node *del = _head->_next;
	while (del != _head)
	{
		if (del->_data == val)
		{
			break;
		}
		tmp = del;
		del = del->_next;
	}
	if (del == nullptr)
	{
		cout << "Remove Error" << endl;
		return;
	}
	if (tmp == _head)
	{
		_head->_next = del->_next;
		tmp->_next = del->_next;
		delete del;
	}
	else
	{
		tmp->_next = del->_next;
		delete del;
	}
}

3、双向链表

基本思想:双向链表与上面单链表和循环链表不同在于,双向链表的每个结点的指针域除了有指向后一个结点的指针还有指向前一个结点的指针,即一个指向前驱一个指向后继。

算法思路:双向链表的操作更灵活,

1、双向链表的头插

(1)

(2)

2、双向链表的尾插

(1)

(2)

3、双向链表的删除

(1)是尾结点

(2)不是尾结点

代码实现:

双向链表的结构

class TwoWardList
{
public:
	TwoWardList()    //构造函数
	{
		_head = new Node();
		_head->_next = nullptr;
		_head->_rear = nullptr;
	}
	~TwoWardList()    //析构函数
	{
		Node* tmp = _head;
		while (tmp != nullptr)
		{
			_head = _head->_next;
			delete tmp;
			tmp = _head;
		}
                delete _head;
	}
	void InsertHead(int val);    //头插
	void InsertTail(int val);    //尾插
	void Remove(int val);        //删除指定值
	bool FindValue(int val);     //查找指定值
	bool Empty();                //判空
	int Front();                 //获取头节点的值
	void DeleteFront();          //删除头节点
	void Show();                 //打印
private:
	class Node
	{
	public:
		Node(int data = 0) :_data(data),_next(nullptr),_rear(nullptr) {}
	private:
		int _data;
		Node* _next;
		Node* _rear;
		friend class TwoWardList;
	};
	Node* _head;
};

双向链表的头插

void InsertHead(int val)
	{
		Node* tmp = new Node(val);
		tmp->_next = _head->_next;
		_head->_next = tmp;
		tmp->_rear = _head;
		if (tmp->_next != nullptr)
		{
			tmp->_next->_rear = tmp;
		}
	}

双向链表的尾插

void InsertTail(int val)
	{
		Node *tmp = new Node(val);
		Node *cur = _head;
		while (cur->_next != nullptr)
		{
			cur = cur->_next;
		}
		cur->_next = tmp;
		tmp->_rear = cur;
		tmp->_next = nullptr;
	}

双向链表的删除

void Remove(int val)
	{
		Node *cur = _head->_next;
		while (cur != nullptr)
		{
			if (cur->_data == val)
			{
				break;
			}
			cur = cur->_next;
		}
		if (cur == nullptr)
		{
			return;
		}
		cur->_rear->_next = cur->_next;
		if (cur->_next != nullptr)
		{
			cur->_next->_rear = cur->_rear;
		}
		delete cur;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值