实现push_back和pop_front的C++自定义列表

C++ custom list implementing push_back and pop_front

本文关键字:C++ 自定义 front 列表 pop push back 实现      更新时间:2023-10-16

我希望有人能帮助我。我正在努力为我正在制作的自定义列表正确实现push_backpop_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值是多少?应该有什么值

  • 如果你试图从空列表中弹出一个项目,会发生什么?

  • 在列表的每一端,端节点应当具有prevnext中的一个是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());
}