【剑指offer】面试题6前置 双向链表的实现

1.主旨

  • 这是对于面试题6中的单向链表的前置实验,本人参照所学的《数据结构(C++语言版)》对双向链表进行了大概实现(单向链表即不使用前继或者后继)。所用的链表实现方式为头尾哨兵节点法,通过两个哨兵位置的恒定性,拓展出双向链的结构形式。

2.考点

  • 考点1:链表实现时的基本节点ListNode的结构形式(value值,前继后继);
  • 考点2:单向/双向链表的基本结构实现,如初始化与析构函数;
  • 考点3:单向/双向链表的功能实现,比如插入函数、删除函数与查找函数等;

3.代码

3.1 基本的节点类
template<typename T> class ListNode
{
public:
	T m_value;
	ListNode<T>* m_pred;
	ListNode<T>* m_succ;
};
3.2 双向链表类
  • 特点:以模板类为基础,实现初始化、析构、秩查询、值查询、位置删除、值删除、首尾节点插入与前后节点插入这些基本功能,并进行了测试通过
  • 问题:不过本代码具体的实现鲁棒性还是不够,对于各种越界的问题没有进行太妥善的处理,主要是为了便于理解以及面试时实现
template<typename T> class List
{
private:
	int m_size;
	ListNode<T>* m_header;
	ListNode<T>* m_laster;
public:
	List() { init(); }
	int getSize() { return m_size; }
	void init();
	T& operator[] (int rank) const;  //const放在最后表const成员函数,无法修改类的成员变量
	ListNode<T>* find(const T& value) const;
	T erase(const T &value);
	T erase(ListNode<T>* node);
	ListNode<T>* insertAsPred(const T &value, ListNode<T>* node);
	ListNode<T>* insertAsSucc(const T &value, ListNode<T>* node);
	ListNode<T>* insertAsHead(const T &value);
	ListNode<T>* insertAsLast(const T &value);
	~List();
};
3.3 各个函数的实现过程
  • 函数的实现过程基本都很易于理解,不易于理解的地方都写了注释
template<typename T> void List<T>::init()
{
	m_header = new ListNode<T>;
	m_laster = new ListNode<T>;
	m_header->m_pred = NULL;
	m_header->m_succ = m_laster;
	m_laster->m_pred = m_header;
	m_laster->m_succ = NULL;
	m_size = 0;
}

template<typename T> T& List<T>::operator[](int rank) const
{
	ListNode<T>* temp = m_header->m_succ;
	while (rank--)
		temp = temp->m_succ;
	return temp->m_value;
}

template<typename T> ListNode<T>* List<T>::find(const T& value) const
{
	ListNode<T>* temp = m_header->m_succ;
	int size = m_size;
	while (size--)
	{
		if (temp->m_value == value)
			return temp;
		temp = temp->m_succ;
	}
	return NULL;
}

template<typename T> T List<T>::erase(const T &value)
{
	ListNode<T>* temp = find(value);
	if (temp == NULL)
		return NULL;
	T temp_value = temp->m_value;
	//1.temp的后继的pred变为temp的前继
	temp->m_succ->m_pred = temp->m_pred;
	//2.temp的前继的succ变为temp的后继
	temp->m_pred->m_succ = temp->m_succ;
	//3.delete当前temp,然后返回被删除的值
	delete temp;
	m_size--;
	return temp_value;
}

template<typename T> T List<T>::erase(ListNode<T>* node)
{
	if (node == NULL)
		return NULL;
	T node_value = node->m_value;
	//1.node的后继的pred变为node的前继
	node->m_succ->m_pred = node->m_pred;
	//2.node的前继的succ变为node的后继
	node->m_pred->m_succ = node->m_succ;
	//3.delete当前node,然后返回被删除的值
	delete node;
	m_size--;
	return node_value;
}

template<typename T> ListNode<T>* List<T>::insertAsPred(const T &value, ListNode<T>* node)
{
	if (node == NULL)
		return NULL;
	ListNode<T>* temp = new ListNode<T>;
	temp->m_value = value;
	//1.原node的前继对象的succ变为temp,原node的前继对象变为temp的pred
	node->m_pred->m_succ = temp;
	temp->m_pred = node->m_pred;
	//2.原node的pred变为temp,原node变为temp的succ
	node->m_pred = temp;
	temp->m_succ = node;
	//3.前继插入完成,返回插入后的node
	m_size++;
	return temp;
}

template<typename T> ListNode<T>* List<T>::insertAsSucc(const T &value, ListNode<T>* node)
{
	if (node == NULL)
		return NULL;
	ListNode<T>* temp = new ListNode<T>;
	temp->m_value = value;
	//1.原node的后继对象的pred变为temp,原node的后继对象变为temp的succ
	node->m_succ->m_pred = temp;
	temp->m_succ = node->m_succ;
	//2.原node的succ变为temp,原node变为temp的pred
	node->m_succ = temp;
	temp->m_pred = node;
	//3.后继插入完成,返回插入后的node
	m_size++;
	return temp;
}

template<typename T> ListNode<T>* List<T>::insertAsHead(const T &value)
{
	ListNode<T>* temp = new ListNode<T>;
	temp->m_value = value;

	m_header->m_succ->m_pred = temp;
	temp->m_succ = m_header->m_succ;

	m_header->m_succ = temp;
	temp->m_pred = m_header;

	m_size++;
	return temp;
}
template<typename T> ListNode<T>* List<T>::insertAsLast(const T &value)
{
	ListNode<T>* temp = new ListNode<T>;
	temp->m_value = value;

	m_laster->m_pred->m_succ = temp;
	temp->m_pred = m_laster->m_pred;

	m_laster->m_pred = temp;
	temp->m_succ = m_laster;

	m_size++;
	return temp;
}

template<typename T> List<T>::~List()
{
	while (m_size)
		erase(m_header->m_succ);
	delete m_laster;
	delete m_header;
}
3.4 测试用主函数与运行结果
int main()
{
	List<int> test;
	for (int i = 0; i < 10; i++)
	{
		test.insertAsHead(i);
		test.insertAsLast(i);
	}
	cout << "test[5]:" << test[5] << endl;
	cout << "test[15]:" << test[15] << endl;
	cout << "test.find(8)->m_value:" << test.find(8)->m_value << endl;
	cout << "test.erase(test.find(4)):" << test.erase(test.find(4)) << endl;
	cout << "test.erase(8)->m_value:" << test.erase(8) << endl;
	cout << "test.insertAsPred(11, test.find(8))->m_value:" << test.insertAsPred(11, test.find(8))->m_value << endl;
	cout << "test.insertAsSucc(13, test.find(5))->m_value:" << test.insertAsSucc(13, test.find(5))->m_value << endl;

	int size = test.getSize();
	for (int i = 0; i < size; i++)
		cout << test[i] << " ";
	cout << endl;
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值