双链表--迭代器、重载方法、使用类重写链表方法

本文介绍了如何使用C++实现双链表,包括节点类的设计,迭代器类的重载方法如后置++,前置++,等,并详细阐述了链表类的实现,包括插入、删除、翻转、排序、合并等操作,以及主函数的测试用例。" 111352610,1005481,X11窗口信息获取:XQueryTree、XGetWindowAttributes和XGetGeometry,"['Linux', 'X11', '窗口管理']

双链表–迭代器、重载方法、使用类重写链表方法

1: 双向链表的节点类

  • 1:数据成员:数据域/前驱指针/后继指针
  • 2:四大默认成员函数:构造/析构/拷贝构造/赋值
  • 3:成员函数
  • 4:新增功能
Node.h
class Node
{
   
   
public :
	friend class List;//友元类
	friend class Iterator;
	Node() :pFront(nullptr), pNext(nullptr)
	{
   
   
	}
	Node(int val, Node* pFront=nullptr, Node* pNext=nullptr);//缺省可以写在声明中,不要写在定义中
	~Node();
private:
	int val;
	Node* pFront;//前驱:指向前一个节点
	Node* pNext;//后驱:指向后一个节点
};
Node.cpp
#include "Node.h"

Node::Node(int val, Node* pFront, Node* pNext):val(val),pFront(pFront),pNext(pNext)
{
   
   
}
Node::~Node()
{
   
   
	pFront = nullptr;
	pNext = nullptr;
}

2: 双想链表迭代器类–重载

  • 迭代器指向的节点: Node* pNode;
  • 构造函数:Iterator(Node* pNode);
  • 友元类:friend class List;
2.1构造函数
Iterator::Iterator(Node* pNode):pNode(pNode)
{
   
   

}
2.2重载后置++
Iterator Iterator::operator++(int)
{
   
   
	Iterator temp = *this;
	pNode = pNode->pNext;
	return temp;
}
2.3重载前置++
Iterator& Iterator::operator++() 
{
   
   
	this->pNode = pNode->pNext;
	return *this;
}
2.4重载后置–
Iterator Iterator::operator--(int)
{
   
   
	Iterator it = *this;
	this->pNode = pNode->pFront;
	return it;
}
2.5重载前置–
Iterator& Iterator::operator--()
{
   
   
	this->pNode = pNode->pFront;
	return *
<think>我们正在讨论C++中如何监控链表的变化。根据引用内容,我们可以考虑使用迭代器来遍历链表,同时结合事件监控机制(如epoll)来监听文件描述符的事件。但链表本身并非文件描述符,因此需要转换思路。实际上,监控数据结构(如链表)的变化通常有几种方法:1.观察者模式(ObserverPattern):在链表发生插入、删除等操作时,通知所有观察者。2.代理模式(ProxyPattern):通过一个代理来访问链表,在代理中拦截修改操作并触发事件。3.使用自定义迭代器:在迭代器中记录访问状态,但这种方法通常用于调试,而不是实时监控。引用[1]中提到了list容器的迭代器实现,引用[4]提到了epoll监控事件。但epoll主要用于I/O多路复用,监控文件描述符,不直接适用于数据结构的变化。因此,我们更倾向于使用观察者模式或代理模式。下面我们设计一个可监控的链表:思路:1.定义一个链表,该内部维护一个链表(如std::list)以及一个观察者列表。2.当链表被修改(插入、删除等)时,触发事件通知所有观察者。3.观察者可以是函数、函数对象或Lambda表达式,它们被注册到链表中。示例代码:```cpp#include<list>#include<functional>#include<vector>//定义事件型enumclassListEvent{INSERT,ERASE,CLEAR,//其他事件...};//前置声明template<typenameT>classObservableList;//观察者回调型template<typenameT>usingListObserver=std::function<void(ObservableList<T>*,ListEvent,constT&)>;template<typenameT>classObservableList{public://注册观察者,返回一个可用于取消注册的函数std::function<void()>registerObserver(constListObserver<T>&observer){observers_.push_back(observer);//返回一个取消注册的lambdareturn[this,&observer](){autoit=std::find(observers_.begin(),observers_.end(),observer);if(it!=observers_.end()){observers_.erase(it);}};}//插入元素voidpush_back(constT&value){data_.push_back(value);notify(ListEvent::INSERT,value);}voidpush_front(constT&value){data_.push_front(value);notify(ListEvent::INSERT,value);}//删除元素voidpop_back(){if(!data_.empty()){Tvalue=data_.back();data_.pop_back();notify(ListEvent::ERASE,value);}}voidpop_front(){if(!data_.empty()){Tvalue=data_.front();data_.pop_front();notify(ListEvent::ERASE,value);}}//清空voidclear(){//注意:这里我们无法提供被删除的单个元素,所以事件型用CLEAR,并且参数T可以忽略data_.clear();notify(ListEvent::CLEAR,T());//使用默认构造的T,但观察者可能会忽略这个值}//其他操作,如insert,erase等,需要似地添加通知//为了简单,这里只实现一部分操作private:voidnotify(ListEventevent,constT&value){for(auto&observer:observers_){observer(this,event,value);}}private:std::list<T>data_;std::vector<ListObserver<T>>observers_;};```使用示例:```cpp#include<iostream>intmain(){ObservableList<int>list;//注册一个观察者,打印插入和删除事件autounregister=list.registerObserver([](ObservableList<int>*list,ListEventevent,constint&value){if(event==ListEvent::INSERT){std::cout<<"Inserted:"<<value<<std::endl;}elseif(event==ListEvent::ERASE){std::cout<<"Erased:"<<value<<std::endl;}elseif(event==ListEvent::CLEAR){std::cout<<"Listcleared."<<std::endl;}});list.push_back(1);//输出:Inserted:1list.push_front(2);//输出:Inserted:2list.pop_back();//输出:Erased:1//取消注册观察者unregister();list.push_back(3);//不会输出return0;}```注意:1.上述实现是线程不安全的,如果在多线程环境下使用,需要加锁。2.为了简化,我们只实现了部分操作(push_back,push_front,pop_back,pop_front,clear)。实际应用中,需要将所有的修改操作都加上通知。另一种方法是继承std::list并重写其修改函数,但std::list的设计并不适合继承(没有虚析构函数,且成员函数非虚)。因此,组合(如上所示)是更安全的方法。引用[1]中关于迭代器的实现,我们可以为这个可观察链表提供迭代器,以便遍历。但注意,迭代器本身并不用于监控,监控是通过观察者模式实现的。如果需要监控链表的具体位置变化(如在特定位置插入删除),则需要在事件中传递位置信息(如迭代器)。但注意,迭代器链表修改后可能失效,因此传递迭代器需要谨慎。我们可以修改事件通知,传递更多信息。例如:```cpptemplate<typenameT>usingListObserver=std::function<void(ObservableList<T>*,ListEvent,constT&,typenamestd::list<T>::iterator)>;```然后在插入时传递插入位置的迭代器,删除时传递被删除元素的位置。但是,在删除后迭代器已经失效,所以传递迭代器可能不安全。因此,我们通常只传递元素值。总结:在C++中监控链表变化,可以通过封装链表并实现观察者模式来达到目的。相关问题:1.观察者模式在C++中如何实现线程安全?2.如何避免观察者模式中的循环引用?3.除了观察者模式,还有哪些设计模式可以用于监控数据结构变化?4.如何为自定义链表实现迭代器(如引用[1]和引用[3]中提到的)?</think>### C++ 监控链表变化的实现方式 在 C++ 中监控链表变化主要有以下实现方式,结合观察者模式、代理模式和迭代器技术: #### 1. **观察者模式(核心方法)** ```cpp #include <list> #include <functional> #include <vector> template <typename T> class ObservableList { public: // 注册监听器 void addListener(std::function<void(const T&, int)> callback) { listeners.push_back(callback); } // 插入元素(触发监控) void push_back(const T& value) { data.push_back(value); notifyListeners(value, INSERT); } // 删除元素(触发监控) void erase(typename std::list<T>::iterator it) { T value = *it; data.erase(it); notifyListeners(value, ERASE); } private: enum Operation { INSERT, ERASE }; std::list<T> data; std::vector<std::function<void(const T&, int)>> listeners; void notifyListeners(const T& value, int op) { for (auto& listener : listeners) { listener(value, op); // 触发所有监听器 } } }; ``` **使用示例**: ```cpp ObservableList<int> list; list.addListener([](int value, int op) { std::cout << (op == 0 ? "插入:" : "删除:") << value << "\n"; }); list.push_back(10); // 输出: 插入:10 auto it = list.begin(); list.erase(it); // 输出: 删除:10 ``` #### 2. **代理迭代器(扩展监控能力)** ```cpp template <typename Iter> class MonitoringIterator { public: MonitoringIterator(Iter it, std::function<void()> onAccess) : current(it), accessCallback(onAccess) {} auto operator*() { accessCallback(); // 访问时触发回调 return *current; } // 其他迭代器操作符重载... private: Iter current; std::function<void()> accessCallback; }; ``` **结合观察者模式使用**: ```cpp auto it = MonitoringIterator( list.begin(), []{ std::cout << "访问链表元素\n"; } ); std::cout << *it; // 输出: 访问链表元素 ``` #### 3. **基于事件驱动的监控(参考 epoll 模型)** ```cpp class ListEventMonitor { public: enum EventType { MODIFY = 0x01, ACCESS = 0x02 }; void watch(int fd, int events) { // 似 epoll_ctl(epfd, EPOLL_CTL_ADD, fd, events) monitoredItems[fd] = events; } void processEvents() { for (auto& [fd, events] : monitoredItems) { if (events & MODIFY) { // 处理修改事件 } } } }; ``` ### 关键实现要点 1. **修改触发机制** -链表修改操作(插入/删除)中嵌入回调通知 - 使用 `std::function` 实现松耦合监听器 2. **访问监控** - 通过自定义迭代器代理访问操作 - 重载 `operator*` 和 `operator->` 注入监控逻辑 3. **线程安全** ```cpp std::mutex mtx; void safeOperation() { std::lock_guard<std::mutex> lock(mtx); // 修改操作 } ``` 4. **性能优化** - 使用移动语义避免监听器调用的拷贝开销 - 异步通知机制(如线程池处理事件) ### 典型应用场景 1. 实时数据同步(如 GUI 列表更新) 2. 内存变更审计(调试/安全场景) 3. 事务性操作(数据库日志记录) 4. 数据流处理(响应式编程) > **提示**:对于标准库 `std::list`,建议使用组合模式(如示例中的 `ObservableList`)而非继承,避免破坏标准容器接口[^1][^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值