实现push_back和pop_front的C++自定义列表
C++ custom list implementing push_back and pop_front
我希望有人能帮助我。我正在努力为我正在制作的自定义列表正确实现push_back
和pop_front
方法。当我运行主程序时,它会冻结,windows报告它停止工作。此列表正用于建立队列。我已经制作了我的队列类,并用stl列表进行了测试(对于我的作业,我还需要制作一个自定义列表),所以我很确定问题出在我的列表中。我想我没有正确编码push_back和pop_front。很抱歉,如果这是一个愚蠢的问题,我试着搜索与我相似的案例,但找不到。如果有任何帮助,我将不胜感激。
我的节点类
template<typename T>
class cNode{
public:
T nodeVal;
cNode<T> *next;
cNode<T> *prev;
cNode<T>();
cNode<T>(const T& v, cNode<T> *n, cNode<T> *p);
};
//Methods
//defualt constructor
template<typename T>
cNode<T>::cNode(){
};
//constructor with value value next and prev
template<typename T>
cNode<T>::cNode(const T& v, cNode<T> *n=NULL, cNode<T> *p=NULL){
nodeVal=v;
next=n;
prev=p;
};
在我的列表中,我注释掉了其他方法,因为它们没有被使用是队列类
#include "cNode.h"
using namespace std;
template <typename T>
class cList{
private:
cNode<T> *frontNode;
cNode<T> *backNode;
int sizeOfList;
public:
cList();
bool empty();
// void push_front(const T& val);
void push_back(const T& val);
void pop_front();
// void pop_back();
T front();
// T back();
int size();
};
//Methods
//Constructor
template <typename T>
cList<T>::cList(){
frontNode = NULL;
backNode = NULL;
};
//Returns true if empty
template<typename T>
bool cList<T>:: empty(){
return frontNode == NULL;
};
//Adds to the back of the list
template<typename T>
void cList<T>:: push_back(const T& val){
cNode<T> *newNode;
newNode = new cNode<T>;
newNode->nodeVal=val;
//inserting in place
newNode->prev = backNode->prev;
newNode->next = backNode;
backNode->prev->next = newNode;
backNode->prev = newNode;
//update size
sizeOfList++;
};
//Removes from the front of the list
template<typename T>
void cList<T>:: pop_front(){
cNode<T> *df;
df = new cNode<T>;
df = frontNode;
df->next->prev=df->prev;
frontNode=frontNode->next;
delete df;
//update size
sizeOfList--;
};
//Returns value of of the front
template<typename T>
T cList<T>:: front(){
return frontNode->nodeVal;
};
//Returns the size of the list
template<typename T>
int cList<T>:: size(){
return sizeOfList;
};
您会发现这里的图表非常有用——绘制指针是绝对确定什么引用了什么的一种方法。
也就是说,这里有一些突出的东西:
-
在构造函数中将CCD_ 3和CCD_ 4初始化为CCD_。当您在第一次
push_back
操作中尝试取消引用这些NULL
时,会发生什么? -
related:单个
push_back
操作后,frontNode
的值是多少?应该有什么值? -
如果你试图从空列表中弹出一个项目,会发生什么?
-
在列表的每一端,端节点应当具有
prev
和next
中的一个是NULL
或者指示它们不指向任何地方的另一个值。
这里的要点是,你有很多NULL
被取消引用,并且你没有更新你需要的所有内容。解决这个问题的方法是用箭头和方框画一个图,然后一步一步地研究当你从一个空列表开始,添加两个或三个节点,然后依次弹出时需要发生什么。
查看代码后发现了什么,使用NULL值初始化CCD_ 14和CCD_,但之后在CCD_ 16中使用CCD_,在使用之前,您需要为它们分配内存。
对您的算法进行少量修改以使其发挥作用:
#include <cassert>
#include <cstdlib>
template <typename T> struct cNode {
T nodeVal;
cNode<T> *next;
cNode<T> *prev;
cNode<T>(const T &v = T(), cNode<T> *n = NULL, cNode<T> *p = NULL)
: nodeVal(v), next(n), prev(p) {}
};
template <typename T> class cList {
private:
cNode<T> head_;
size_t sizeOfList_;
typedef cNode<T> NT;
public:
cList() : sizeOfList_(0) {
head_.next = &head_;
head_.prev = &head_;
}
~cList() {
for (NT *p = begin(); p != end();) {
NT *next = p->next;
delete p;
p = next;
}
}
cNode<T> *cbegin() const { return head_.next; }
cNode<T> *begin() { return head_.next; }
cNode<T> *end() { return &head_; }
bool empty() const { return head_.next == &head_; }
void push_back(const T &val) {
NT *newNode = new NT(val);
NT *prev_end = end()->prev;
prev_end->next = newNode;
newNode->prev = prev_end;
newNode->next = end();
end()->prev = newNode;
++sizeOfList_;
}
void pop_front() {
if (empty())
return;
NT *next_in_list = begin()->next;
NT *prev_in_list = begin()->prev;
delete begin();
head_.next = next_in_list;
if (prev_in_list == end())
end()->prev = end();
--sizeOfList_;
}
T front() const {
assert(!empty());
return cbegin()->nodeVal;
}
size_t size() const { return sizeOfList_; }
};
int main() {
cList<int> l;
assert(l.size() == 0);
assert(l.empty());
l.push_back(10);
assert(!l.empty());
assert(l.size() == 1);
assert(l.front() == 10);
l.pop_front();
assert(l.size() == 0);
assert(l.empty());
for (int i = 5; i < 17; ++i)
l.push_back(i);
assert(l.size() == (17 - 5));
assert(l.front() == 5);
assert(!l.empty());
{
cNode<int> *p;
int i;
for (p = l.begin(), i = 5; p != l.end(); p = p->next, ++i) {
assert(p->nodeVal == i);
}
assert(i == 17);
}
l.pop_front();
assert(l.size() == (17 - 5 - 1));
assert(l.front() == 6);
assert(!l.empty());
l.pop_front();
assert(l.size() == (17 - 5 - 2));
assert(l.front() == 7);
assert(!l.empty());
}
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- C++自定义比较函数
- 如何比较自定义类的std::变体
- std::设置自定义比较器
- 如何正确实现和访问运算符的各种自定义枚举器
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 自定义先决条件对移动分配运算符有效吗
- 使用VS Code和CMake Tools运行自定义命令
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- std::ranges::elements_view,用于自定义类似元组的数据
- 跟随整数索引列表的自定义类迭代器
- 参数化自定义CMake工具链
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 如何在自定义类中启用'auto loops'?
- 使用QJsEngine在Qt中注册自定义类型
- Qt自定义QPush按钮未显示在布局上
- 自定义对象的dlib序列化在gcc中失败
- 自定义创建QFuture
- 如何在QT中的自定义视频小工具t上绘制矩形