数据结构2.2 链表的实现

链表的实现

  • 不管链表中有无数据,我们都保持两个节点:头(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)
    由以上时间复杂度可以发现:
    链表适合频繁插入和删除的场景,但不适合频繁随机访问的场景。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值