努力将双向链接的通用列表转换为循环列表。 (段错误)
Struggling to transfer a doubly linked generic list to circular. (segfault)
所以我得到了这个非循环双重 linked 列表示例,我发现很难将其转换为循环列表示例。 (在//添加的行上出现段错误)
任何建议都会很好。
提前致谢。
另外,我应该使用重载来处理不同类型的输入吗?我如何操纵它们? link 有一个合适的例子(真的找不到)会让我很高兴。
main.cpp
#include <iostream>
#include "dlring.cpp"
int main()
{
dlring<int> dlist;
dlist.Append( 11 );
dlist.Push( 100 );
while(dlist)
std::cout << dlist.pop_back() << " ";
}
dlring.h
template <typename T>
class dlring
{
struct node
{
T data;
node* prev;
node* next;
node(T t, node* p, node* n) : data(t), prev(p), next(n) {}
};
node* head;
node* tail;
public:
dlring() : head(nullptr), tail (nullptr) {}
bool empty() const { return ( !head || !tail ); }
operator bool() const { return !empty(); }
//Yes, I also wish to implement this bool stuff otherwise.
void Append(T);
void Push(T);
T pop_back();
T pop_front();
~dlring()
{
while(head)
{
node* temp(head);
head=head->next;
delete temp;
}
}
};
dlring.cpp
#include "dlring.h"
#include <iostream>
template <typename T>
void dlring<T>::Append(T data)
{
tail = new node(data, tail, head); //changed NULL=>head
if( tail->prev )
{
tail->prev->next = tail;
head->prev = tail; //added
}
if( empty() )
head = tail;
}
template <typename T>
void dlring<T>::Push(T data)
{
head = new node(data, tail, head); //changed NULL=>tail
if( head->next )
{
head->next->prev = head;
tail->next = head; //added
}
if( empty() )
tail = head;
}
template<typename T>
T dlring<T>::pop_back()
{
if( empty() )
std::cout<<"List empty";
node* temp(tail);
T data( tail->data );
tail = tail->prev ;
if( tail )
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
head = nullptr; //NULL=>nullptr
delete temp;
return data;
}
template<typename T>
T dlring<T>::pop_front()
{
if( empty() )
std::cout<<"List empty";
node* temp(head);
T data( head->data );
head = head->next ;
if( head )
{
head->prev = tail; //NULL=>nullptr=>tail
tail->next = head;
}
else
tail = nullptr; //NULL=>nullptr
delete temp;
return data;
}
您的问题出在 pop_back
函数中:
node * temp(tail);
T data(tail->data);
tail = tail->prev;
if(tail)
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
{
head = nullptr; //NULL=>nullptr
}
delete temp;
当列表中只有一个节点时,tail
不是 null
- 这意味着 if
条件将被满足,并且将命中以下代码:
tail->next = head; //null=>head;
head->prev = tail; //added
但是这段代码什么也没做,因为tail
和head
是一回事。然后删除列表中唯一的节点,head
和 tail
不再指向任何内容。为了解决这个问题,你需要一个更好的方法来检测删除后列表是否为空,并稍微改变删除代码:
if (tail != temp)
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
{
head = nullptr; //NULL=>nullptr
tail = nullptr;
}
delete temp;
temp = nullptr;
所以我得到了这个非循环双重 linked 列表示例,我发现很难将其转换为循环列表示例。 (在//添加的行上出现段错误) 任何建议都会很好。 提前致谢。 另外,我应该使用重载来处理不同类型的输入吗?我如何操纵它们? link 有一个合适的例子(真的找不到)会让我很高兴。
main.cpp
#include <iostream>
#include "dlring.cpp"
int main()
{
dlring<int> dlist;
dlist.Append( 11 );
dlist.Push( 100 );
while(dlist)
std::cout << dlist.pop_back() << " ";
}
dlring.h
template <typename T>
class dlring
{
struct node
{
T data;
node* prev;
node* next;
node(T t, node* p, node* n) : data(t), prev(p), next(n) {}
};
node* head;
node* tail;
public:
dlring() : head(nullptr), tail (nullptr) {}
bool empty() const { return ( !head || !tail ); }
operator bool() const { return !empty(); }
//Yes, I also wish to implement this bool stuff otherwise.
void Append(T);
void Push(T);
T pop_back();
T pop_front();
~dlring()
{
while(head)
{
node* temp(head);
head=head->next;
delete temp;
}
}
};
dlring.cpp
#include "dlring.h"
#include <iostream>
template <typename T>
void dlring<T>::Append(T data)
{
tail = new node(data, tail, head); //changed NULL=>head
if( tail->prev )
{
tail->prev->next = tail;
head->prev = tail; //added
}
if( empty() )
head = tail;
}
template <typename T>
void dlring<T>::Push(T data)
{
head = new node(data, tail, head); //changed NULL=>tail
if( head->next )
{
head->next->prev = head;
tail->next = head; //added
}
if( empty() )
tail = head;
}
template<typename T>
T dlring<T>::pop_back()
{
if( empty() )
std::cout<<"List empty";
node* temp(tail);
T data( tail->data );
tail = tail->prev ;
if( tail )
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
head = nullptr; //NULL=>nullptr
delete temp;
return data;
}
template<typename T>
T dlring<T>::pop_front()
{
if( empty() )
std::cout<<"List empty";
node* temp(head);
T data( head->data );
head = head->next ;
if( head )
{
head->prev = tail; //NULL=>nullptr=>tail
tail->next = head;
}
else
tail = nullptr; //NULL=>nullptr
delete temp;
return data;
}
您的问题出在 pop_back
函数中:
node * temp(tail);
T data(tail->data);
tail = tail->prev;
if(tail)
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
{
head = nullptr; //NULL=>nullptr
}
delete temp;
当列表中只有一个节点时,tail
不是 null
- 这意味着 if
条件将被满足,并且将命中以下代码:
tail->next = head; //null=>head;
head->prev = tail; //added
但是这段代码什么也没做,因为tail
和head
是一回事。然后删除列表中唯一的节点,head
和 tail
不再指向任何内容。为了解决这个问题,你需要一个更好的方法来检测删除后列表是否为空,并稍微改变删除代码:
if (tail != temp)
{
tail->next = head; //null=>head;
head->prev = tail; //added
}
else
{
head = nullptr; //NULL=>nullptr
tail = nullptr;
}
delete temp;
temp = nullptr;