相比于单链表,双向循环链表的插入操作还是比较饶人的,初学者一开始可能会比较难理解,可以画个图会比较理解。
一.从头部插入元素(头插法)
1.将当前新增节点的前驱节点指向头节点的前驱节点
2.将当前新增节点的后继节点指向头节点
3.头节点的前驱节点的后继节点指向当前新增节点
4.头节点的前驱节点指向当前新增节点
//从头部插入元素
void push_front(valueType value)
{
Node<valueType> *node = new Node<valueType>();
node->m_data = value;
node->m_nextNode = m_head->m_nextNode; //当前新增节点的前驱节点指向头节点的前驱节点
node->m_preNode = m_head; //当前新增节点的后继节点指向头节点
m_head->m_nextNode->m_preNode = node; //头节点的前驱节点的后继节点指向当前新增节点
m_head->m_nextNode = node; //头节点的前驱节点指向当前新增节点
}
一.从尾部插入元素(尾插法)
1.将新增节点的后继节点指向头节点的后继节点指向的节点
2.将新增节点的前驱节点指向头节点
3.头节点的后继节点也就是当前链表的尾部节点,将尾部节点的前驱节点指向新增节点
4.头节点的后继节点指向当前新增节点
//从尾部插入元素
void push_back(valueType value)
{
Node<valueType> *node = new Node<valueType>();
node->m_data = value;
node->m_preNode = m_head->m_preNode; //后继节点指向头节点的后继节点指向的节点
node->m_nextNode = m_head; //前驱节点指向头节点
//头节点的后继节点也就是当前链表的尾部节点,将尾部节点的前驱节点指向node
m_head->m_preNode->m_nextNode= node;
m_head->m_preNode = node; //头节点的后继节点指向node
}
完整代码:
#include <iostream>
//双向循环链表节点
template<class T>
class Node {
public:
Node(): m_nextNode(nullptr), m_preNode(nullptr){}
T m_data; //数据域
Node *m_nextNode; //前驱指针
Node *m_preNode; //后驱指针
};
//双向循环链表类
template<class valueType>
class doubleList
{
public:
doubleList()
{
m_head = new Node<valueType>();
m_head->m_nextNode = m_head;
m_head->m_preNode = m_head;
}
~doubleList() {
Node<valueType> *node=nullptr;
while (m_head->m_nextNode!=m_head->m_preNode)
{
node = m_head->m_nextNode;
m_head->m_nextNode = node->m_nextNode;
node->m_nextNode->m_preNode = m_head;
delete node;
}
delete m_head;
}
//从尾部插入元素
void push_back(valueType value)
{
Node<valueType> *node = new Node<valueType>();
node->m_data = value;
node->m_preNode = m_head->m_preNode; //后继节点指向头节点的前驱节点指向的节点
node->m_nextNode = m_head; //前驱节点指向头节点
//头节点的后继节点也就是当前链表的尾部节点,将尾部节点的前驱节点指向node
m_head->m_preNode->m_nextNode= node;
m_head->m_preNode = node; //头节点的后继节点指向node
}
//从头部插入元素
void push_front(valueType value)
{
Node<valueType> *node = new Node<valueType>();
node->m_data = value;
node->m_nextNode = m_head->m_nextNode; //当前新增节点的前驱节点指向头节点的前驱节点
node->m_preNode = m_head; //当前新增节点的后继节点指向头节点
m_head->m_nextNode->m_preNode = node; //头节点的前驱节点的后继节点指向当前新增节点
m_head->m_nextNode = node; //头节点的前驱节点指向当前新增节点
}
//从双向循环链表中删除元素,删除第一个出现的指定元素
void deleteFirst(valueType value)
{
Node<valueType> *node = m_head->m_nextNode;
while (node!= m_head)
{
if (node->m_data==value)
{
//待删除节点的后继节点的前驱节点指向待删除节点的前驱节点
node->m_preNode->m_nextNode = node->m_nextNode;
//待删除节点的前驱节点的后继节点指向待删除节点的后继节点
node->m_nextNode->m_preNode = node->m_preNode;
delete node; //释放删除节点的空间
return;
}
node = node->m_nextNode;
}
}
//从双向循环链表中删除所有指定元素
void deleteAll(valueType value)
{
Node<valueType> *node = m_head->m_nextNode;
while (node != m_head)
{
if (node->m_data == value)
{
//待删除节点的后继节点的前驱节点指向待删除节点的前驱节点
node->m_preNode->m_nextNode = node->m_nextNode;
//待删除节点的前驱节点的后继节点指向待删除节点的后继节点
node->m_nextNode->m_preNode = node->m_preNode;
Node<valueType> *delNode = node; //delNode记录下要删除的节点地址
node = node->m_preNode; //将node移动到上一节点
delete delNode; //释放删除节点的空间
}
node = node->m_nextNode;
}
}
int size()
{
Node<valueType> *node = m_head->m_nextNode;
int listSize = 0;
while (node != m_head)
{
node = node->m_nextNode;
listSize++;
}
return listSize;
}
/**************************************************
* @brief: 从单链表中指定位置开始查找,查找第一个出现的指定元素,
* @param: value:要查找的元素
* @param: pos:从pos位置开始查找
* @return: 返回查找到的元素所在链表中的位置,从pos后的位置,如果没找到返回-1
**************************************************/
int findFirst(valueType value, int pos)
{
if (pos < 0 || pos>= this->size() ) return -1;
Node<valueType> *posNode = m_head->m_nextNode; //指向pos所在位置的指针
for (int i=0;i<=pos;i++)
{
posNode = posNode->m_nextNode;
}
int valuePos = 0;
while (posNode != m_head)
{
if (posNode->m_data == value)
{
return valuePos+1;
}
valuePos++;
posNode = posNode->m_nextNode;
}
return -1;
}
doubleList<valueType>& operator<<(const valueType&value)
{
this->push_back(value);
return *this;
}
void printfAll()
{
Node<valueType> *node = m_head->m_nextNode;
while (node != m_head)
{
std::cout << node->m_data << " ";
node = node->m_nextNode;
}
std::cout << std::endl;
}
private:
Node<valueType> *m_head;
};
int main()
{
doubleList<int> dbList;
dbList << 1 << 3 << 4 << 2 << 4 << 1;
std::cout << "list size :" << dbList.size()<<std::endl;
dbList.printfAll();
std::cout << "from 0 pos find 4 first pos is :" << dbList.findFirst(4, 0) << std::endl;
std::cout << "from dbList.findFirst(4, 0) pos find 4 first pos is :" << dbList.findFirst(4, 2) << std::endl;
dbList.push_back(22);
dbList.push_front(2334);
dbList.printfAll();
dbList.deleteFirst(4);
std::cout << "delete first 4" << std::endl;
dbList.printfAll();
std::cout << "4 first pos :" << dbList.findFirst(4,0) << std::endl;
dbList.deleteAll(1);
dbList.printfAll();
return 0;
}