链表的实现
- 不管链表中有无数据,我们都保持两个节点:头(m_pHead)和尾(m_pTail)
- 双向链表:每个节点有指向后一个节点的指针和指向上一个节点的指针。
实现代码如下:
以下代码实现了链表的增加和删除功能。
其中每段头文件中的代码都对应了.cpp文件中的代码。如头文件中的push_front那段代码,对应了.cpp文件中的**//在最前面添加元素**之后的三行代码。
.cpp文件中的代码:
#include "stdafx.h"
#include<iostream>
#include<list>
#include"Mylist1.h"
using namespace std;
int main(int argc, char* argv[])
{
CMylist1 mylist;
//在最前面添加元素
/*mylist.push_front(1);
mylist.push_front(2);
mylist.push_front(3);*/
//在最后面添加元素
/*mylist.push_back(0x10);
mylist.push_back(0x20);
mylist.push_back(0x30);
*/
//在任意位置添加元素
mylist.push_back(10);
mylist.push_back(20);
mylist.push_back(30);
mylist.push_back(40);
for (auto it = mylist.begin(); it != mylist.end(); it++)
{
cout << *it << " ";
}
cout << endl;
for (auto it = mylist.begin(); it != mylist.end(); it++)
{
if (*it == 30)
{
it = mylist.insert(it, 100);
cout << *it << " ";
it++;
continue;
//break;
}
cout << *it << " ";
}
cout << endl;
//(在任意位置)删除元素
// mylist.push_back(10);
// mylist.push_back(20);
// mylist.push_back(30);
// mylist.push_back(40);
// for (auto it = mylist.begin();
// it != mylist.end(); it++)
// {
// if (*it == 30)
// {
// it = mylist.erase(it);
// }
// cout << *it << " ";
// }
// cout << endl;
return 0;
}
头文件Mylist1.h中的代码:
#pragma once
#define TYPE int
struct CNode
{
public:
CNode(TYPE arg) :data(arg),
m_pNext(nullptr),
m_pPrev(nullptr)
{
}
TYPE data;
CNode* m_pNext;
CNode* m_pPrev;
};
class CMylist1
{
public:
CNode* m_pHead;
CNode* m_pTail;
CMylist1()
{
/*Head|Tail
*/
m_pHead = new CNode(TYPE());
m_pTail = new CNode(TYPE());
m_pHead->m_pNext = m_pTail;
m_pHead->m_pPrev = nullptr;
m_pTail->m_pNext = nullptr;
m_pTail->m_pPrev = m_pHead;
}
void push_front(int arg)
{
/*Head|1|2|Tail
Head|new|1|2|Tail*/
CNode* pNewNode = new CNode(arg);
CNode* pFirstNode = m_pHead->m_pNext;
m_pHead->m_pNext = pNewNode;
pFirstNode->m_pPrev = pNewNode;
pNewNode->m_pNext = pFirstNode;
pNewNode->m_pPrev = m_pHead;
}
void push_back(int arg)
{
/*
Head|1|2|Tail
Head|1|2|new|Tail
*/
CNode* pNewNode = new CNode(arg);
//改变指针之间的关系(拓扑关系)
CNode* pLastNode = m_pTail->m_pPrev;
pLastNode->m_pNext = pNewNode;
pNewNode->m_pPrev = pLastNode;
pNewNode->m_pNext = m_pTail;
m_pTail->m_pPrev = pNewNode;
}
~CMylist1()
{
}
struct iterator
{
iterator(CNode* pNode) :
m_pNode(pNode)
{
}
bool operator==(iterator otherIt)
{
return m_pNode == otherIt.m_pNode;
}
bool operator!=(iterator otherIt)
{
return m_pNode != otherIt.m_pNode;
}
iterator operator++(int)
{
//下一项
m_pNode = m_pNode->m_pNext;
return m_pNode;
}
TYPE& operator*()
{
return (m_pNode->data);
}
CNode* m_pNode;
};
iterator begin()
{
return m_pHead->m_pNext;
}
iterator end()
{
return m_pTail;
}
iterator insert(iterator it, TYPE val)
{
/*
Head|1|2|it|Tail
Head|1|2|new|it|Tail
*/
CNode* pNewNode = new CNode(val);
CNode* pItNode = it.m_pNode;
CNode*pNode2 = pItNode->m_pPrev;
pItNode->m_pPrev = pNewNode;
pNode2->m_pNext = pNewNode;
pNewNode->m_pNext = pItNode;
pNewNode->m_pPrev = pNode2;
return pNewNode;
}
iterator erase(iterator it)
{
/*
Head|1|2|it|3|Tail
Head|1|2|3|Tail
*/
CNode* pDelNode = it.m_pNode;
CNode* pPrevNode = pDelNode->m_pPrev;
CNode* pNextNode = pDelNode->m_pNext;
pPrevNode->m_pNext = pNextNode;
pNextNode->m_pPrev = pPrevNode;
if (pDelNode != nullptr)
{
delete pDelNode;
pDelNode = nullptr;
}
return pNextNode;
}
};
链表总结
时间复杂度
- 在头和尾插入或删除一个元素:O(1)
- 在指定位置插入或删除元素:O(1)
- 寻找等于某值的元素O(n)
- 访问第i个元素O(n)
由以上时间复杂度可以发现:
链表适合频繁插入和删除的场景,但不适合频繁随机访问的场景。