我试图用这样的C ++中的暴露节点实现一个简单的双向链表 (省略了一些方法,应该非常清楚它们的作用):
template<typename T>
class Node
{
public:
Node(T _value)
{
m_Data = _value;
m_HasParent = false;
m_HasNext = false;
m_Parent = NULL;
m_Next = NULL;
}
void insertAfter(Node<T>* _item)
{
m_Next = _item;
m_HasNext = true;
_item->insertBefore(this);
}
void insertBefore(Node<T>* _item)
{
if(m_HasParent)
{
m_Parent->insertAfter(_item);
_item->insertAfter(this);
}
else
{
m_Parent = _item;
m_HasParent = true;
}
}
private:
T m_Data;
Node<T>* m_Parent;
Node<T>* m_Next;
bool m_HasParent;
bool m_HasNext;
};
template<typename T>
class LinkedList
{
public:
LinkedList()
{
m_Root = NULL;
m_HasRoot = false;
}
~LinkedList()
{
if(m_HasRoot)
{
delete m_Root;
}
}
void pushFront(T _value)
{
if(m_HasRoot)
{
Node<T>* node = new Node<T>(_value);
m_Root->insertBefore(node);
node->insertAfter(m_Root);
m_Root = node;
}
else
{
m_Root = new Node<T>(_value);
m_HasRoot = true;
}
}
void pushBack(T _value)
{
if(m_HasRoot)
{
Node<T>* last = m_Root;
while(true)
{
if(last->getHasNext())
{
last = last->getNext();
}
else
{
break;
}
}
Node<T>* node = new Node<T>(_value);
last->insertAfter(node);
return;
}
else
{
m_Root = new Node<T>(_value);
m_HasRoot = true;
}
}
T operator[](int _i)
{
Node<T>* last = m_Root;
for(int i = 0; i <= _i; i++)
{
if(last->getHasNext())
{
last = last->getNext();
}
else
{
break;
}
}
return last->getData();
}
private:
Node<T>* m_Root;
bool m_HasRoot;
};
但是,在执行以下小测试时:
int main(int argc, char** argv)
{
LinkedList<int> l;
l.pushBack(0);
l.pushBack(1);
l.pushBack(2);
l.pushBack(3);
int count = l.getCount();
std::cout << "count: " << count << std::endl;
for(int i = 0; i < count; i++)
{
std::cout << "Value at [" << i << "]: " << l[i] << std::endl;
}
std::string s;
std::cin >> s;
return 0;
}
我希望看到按此顺序打印的数字0, 1, 2, 3
,但这就是我得到的:
出于某种原因,插入背部并不是很有效。我发现我的代码没有任何根本错误,有人能发现问题吗?这是在MinGW 5.1,64bit,Windows 10 64bit上。但是,在runnable.com上执行此问题时,一切似乎都运行得很好?见this draft。这是MinGW中的错误还是我的一些错误?
现在这很奇怪,有时似乎在runnable中运行,有时它会产生与我本地机器相同的结果......我完全糊涂了。
答案 0 :(得分:3)
尝试将ListWidget::operator[]
内的循环条件从i <= _i
更改为i < _i
。 _i
等于0
。
标志是您从第二个元素开始打印,即1
并打印最后一个元素两次。你忘记了根节点。
请注意,您正在检查某个节点是否有成功者,但您没有检查该列表是否为空(m_root != nullptr
)。使其保持一致 - 要么删除UB的所有可能情况,要么不检查任何内容。