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

时间:2015-11-13 04:26:00

标签: c++ list

我希望有人可以帮助我。我正在努力为我制作的自定义列表正确实施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;
};

2 个答案:

答案 0 :(得分:0)

查看代码后发现了什么, 你使用NULL值初始化backNodefrontNode, 但在push_back之后你使用operator->代替他们, 在使用之前,你需要为它们分配内存。

对算法进行少量修改以使其有效:

#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());
}

答案 1 :(得分:0)

你会发现这里的图表非常有用 - 绘制指针是绝对确定引用内容的一种方法。

那就是说,这里有一些跳出来的东西:

  • 您在构造函数中初始化frontNodebackNodeNULL。当您在第一次NULL操作期间尝试取消引用这些push_back时会发生什么?

  • 相关:单个frontNode操作后push_back的值是多少?

  • 具有什么价值?

  • 如果您尝试从空列表中弹出项目会发生什么?

  • 在列表的每一端,结束节点应该有prevnext之一为NULL或另一个值,表明它们无处可寻。

这里的要点是,您已经取消了很多NULL被取消引用,并且您没有更新您需要的所有内容。解决问题的方法是制作带有箭头和方框的图表,然后一步一步地介绍当你从一个空列表开始,向它添加两个或三个节点然后连续弹出时需要发生的事情他们离开了。