C++ 双链表的实现
我试图实现一个链表,但我完全迷路了。我到处都是断点,特别是用擦除法。每当我改变擦除方法时,不可避免地会出现一些错误。我遇到了指针错误、析构函数问题,这些问题只有在调用erase方法时才会出现,等等 以下是我目前掌握的情况: 头文件:C++ 双链表的实现,c++,pointers,linked-list,iterator,C++,Pointers,Linked List,Iterator,我试图实现一个链表,但我完全迷路了。我到处都是断点,特别是用擦除法。每当我改变擦除方法时,不可避免地会出现一些错误。我遇到了指针错误、析构函数问题,这些问题只有在调用erase方法时才会出现,等等 以下是我目前掌握的情况: 头文件: #pragma once class IntList { private: class IntNode { public: IntNode(int v, IntNode *pr, IntNode *nx); ~In
#pragma once
class IntList {
private:
class IntNode {
public:
IntNode(int v, IntNode *pr, IntNode *nx);
~IntNode();
IntNode* previous;
IntNode* next;
class iterator {
public:
iterator(IntNode* t);
int& operator*();
iterator& operator++();
iterator& operator--();
bool operator!=(iterator other)const;
private:
IntNode* target;
};
private:
int value;
};
IntNode* head;
IntNode* tail;
int count;
public:
IntList();
~IntList();
void push_back(int v);
void pop_back();
int size() const { return count; }
typedef IntNode::iterator iterator;
iterator begin();
iterator end();
//unsigned int size() const;
void push_front(int value);
bool empty() const;
int& front();
int& back();
void clear();
iterator erase(iterator position);
};
实施:
#include "IntList.h"
#include <stdexcept>
IntList::IntList() : head{ nullptr }, tail{ nullptr }, count{ 0 }
{}
IntList::~IntList() {
while (head) {
head = head->next;
delete head;
}
}
void IntList::push_back(int v) {
tail = new IntNode{ v, tail, nullptr };
if (!head) { head = tail; }
count += 1;
}
void IntList::pop_back() {
tail = tail->previous;
delete tail->next;
count -= 1;
}
IntList::iterator IntList::begin()
{
return iterator{ head };
}
IntList::iterator IntList::end() {
return iterator{ nullptr };
}
void IntList::push_front(int value) {
head = new IntNode{ value, nullptr, head };
if (!tail) { tail = head; }
count += 1;
}
bool IntList::empty() const{
return (count==0);
}
int& IntList::front() {
return *begin();
}
int& IntList::back() {
return *begin();
}
void IntList::clear() {
head = nullptr;
tail = nullptr;
count = 0;
}
IntList::iterator IntList::erase(iterator position) {
int midpointL = 0;
for (iterator index = begin(); index != position; ++index) {
midpointL++;
}
if (midpointL == 0) {
head = head->next;
}
else if (midpointL == count) {
tail = tail->previous;
}
else {
// Move head to get a reference to the component that needs to be deleted
for (int i = 0; i < midpointL; i++) {
head = head->next;
}
// Change the previous and next pointers to point to each other
(head->previous)->next = (head->next);
(head->next)->previous = (head->previous);
for (int i = midpointL-1; i > 0; i++) {
head = head->previous;
}
}
count-=1;
return position;
}
IntList::IntNode::IntNode(int v, IntNode * pr, IntNode * nx)
: previous{ pr }, next{ nx }, value{ v }
{
if (previous) { previous->next = this; }
if (next) { next->previous = this; }
}
IntList::IntNode::~IntNode() {
if (previous) previous->next = next;
if (next) next->previous = previous;
}
IntList::IntNode::iterator::iterator(IntNode* t)
: target{ t }
{}
int& IntList::IntNode::iterator::operator*() {
if (!target) { throw std::runtime_error{ "Deferenced sentinel iterator." }; }
return target->value;
}
IntList::IntNode::iterator& IntList::IntNode::iterator::operator++()
{
if (target) { target = target->next; }
return *this;
}
IntList::IntNode::iterator& IntList::IntNode::iterator::operator--()
{
if (target) { target = target->previous; }
return *this;
}
bool IntList::IntNode::iterator::operator!=(iterator other)const
{
return (!(target == other.target));
}
有人能帮我指出正确的方向吗
谢谢 让我们在这里快速回顾一下:
IntList::~IntList() {
while (head) {
head = head->next;
delete head;
}
}
你应该改为:
IntList::~IntList() {
while (head) {
IntNode* newHead = head->next;
delete head;
head = newHead;
}
}
当您删除下一个对象,然后在下一次迭代中尝试访问它时
void IntList::pop_back() {
tail = tail->previous;
delete tail->next;
count -= 1;
}
在这里,你没有检查尾部是否为空或者是否指向头部。空的条件是什么?可能是计数=0? 在这种情况下,您可以删除不存在的下一个节点
IntList::iterator IntList::end() {
return iterator{ nullptr };
}
…结束为空?ebd应该是你的尾巴
int& IntList::back() {
return *begin();
}
那是开始,不是回来
void IntList::clear() {
head = nullptr;
tail = nullptr;
count = 0;
}
清除应释放列表中的所有对象。你在这里制造垃圾
我在这里停了下来,很抱歉,只是喝杯咖啡休息一下。但你应该仔细看看:
*空指针用法
*不需要时删除节点列表项
*注意不要使用无效的指针,比如head->previous->next我在某处看到的
您必须自下而上检查代码。希望这些最初的提示能帮助你完成学习过程
玩得开心,
Ste1已存在。2你可能真的只想用一个,而在现实生活中,链表是一个糟糕的数据结构,性能非常糟糕。我想他这样做是为了练习,链表也有自己的用法,例如当您需要从列表中插入/删除固定时间时,例如在实时计算中,时间可预测性是绝对关键的&IntList::back{return begin;}-这看起来是错误的。你为什么要结束,为什么要开始?这根本没有道理。@BlooB研究方面是有效的,但OP本可以提到他这样做是为了学习。大O参数在现实生活中并不适用-现代CPU真的不喜欢在内存中到处追逐指针,而这正是您在寻找插入点时要做的-向量对预取程序更友好。当然,理论上列表插入速度更快,但在实践中;vector每次都打败他们。我同意@JesperJuhl的评估,但在一个低端微控制器上,没有现代处理器的所有功能,链表并没有那么糟糕,vector可能是一个等待发生的内存碎片死亡。请注意,在这个世界中,您预先分配了所有列表节点,当您用完时。。。好的,你做什么取决于你需要节点做什么。