一个简单的双向链表的例子
来源:互联网 发布:高考必知文学常识 编辑:程序博客网 时间:2024/06/09 20:02
题目描述:
Implement the class with given header.
As you guess, DouList means 逗list, very funny.
to_str() function means displaying the list with std::string, formating like [1, 2, 3, 4] , [2] or [] (empty list)(notice white-space)
operator<< means output the string from ‘to_str()’
struct DouListNode is the node of DouList.
if you have any doubt in function of the member methods, take a look at STL.
中文描述概要:
0 大概是让你实现一个双头列表。
1 如果对成员函数的作用有疑问,参照STL的常规含义。
2 to_str()就是把list输出成标准字符串的形式。operator<<则打印to_str()得到的字符串。
测试文件:
//created by my TA#include <iostream>#include "DouList.h"using namespace std;DouList list1, list2;void display() { cout << list1.empty() << ':' << list1 << endl; cout << list2.empty() << ':' << list2.to_str() << endl;}int main() { display(); list1.push_front(894); list2.push_back(2136); cout << list1.front() << ',' << list1.back() << endl; cout << list2.front() << ',' << list2.back() << endl; display(); list1.push_back(214); list2.push_front(931); cout << list1.front() << ',' << list1.back() << endl; cout << list2.front() << ',' << list2.back() << endl; display(); for (int i = 0; i < 10; ++i) { int t; cin >> t; list1.push_back(t); list2.push_front(t); } display(); for (int i = 0; i < 5; ++i) { list1.pop_front(); list2.pop_back(); } display(); DouList list3(list1); list1 = list2; cout << list1 << endl; cout << list3 << endl; return 0;}
解决代码:
头文件:
#ifndef SSCPP2014_DOULIST_A_H#define SSCPP2014_DOULIST_A_H#include <string>struct DouListNode { int elem; DouListNode *prev, *next; DouListNode(int e = 0, DouListNode *p = 0, DouListNode *n = 0) { elem = e; prev = p; next = n; }};class DouList { private: DouListNode *m_head, *m_tail; public: DouList(); DouList(const DouList &src); ~DouList(); void clear(); bool empty() const; std::string to_str() const; int front() const; int back() const; void push_front(const int &e); void push_back(const int &e); void pop_front(); void pop_back(); void operator=(const DouList &other); friend std::ostream& operator<<(std::ostream &out, const DouList &list); // non-meaning static value static int _error_sign; // for illegal front()/back()};#endif
具体实现的cpp文件:
#include "DouList.h"#include "sstream"using namespace std;DouList::DouList() {m_head = NULL, m_tail = NULL;}DouList::DouList(const DouList &src) { m_head = m_tail = NULL; *this = src;}DouList::~DouList() {clear();}void DouList::operator=(const DouList &other) { clear(); if (other.m_head != NULL) { DouListNode *current = new DouListNode(other.m_head->elem), *prev; DouListNode *temp = other.m_head; m_head = current; while (temp->next != NULL) { temp = temp->next; prev = current; current = new DouListNode(temp->elem); current->prev = prev; prev->next = current; } m_tail = current; }}void DouList::clear() { if (m_head != NULL) { DouListNode* p = m_head, *temp; while (p != NULL) { temp = p; p = p->next; delete temp; } m_head = m_tail = NULL; }}bool DouList::empty() const {return (m_head == NULL) ? true : false;}string DouList::to_str() const { string str, temp; stringstream ss; str += "["; DouListNode* t = m_head; if (t == NULL) { str += "]"; return str; } while (t->next != NULL) { ss << t->elem; ss >> temp; str += temp + ", "; temp = "", ss.clear(); t = t->next; } ss << t->elem; ss >> temp; str += temp + "]"; return str;}int DouList::front() const {if (m_head != NULL) return m_head->elem;}int DouList::back() const {if (m_tail != NULL) return m_tail->elem;}void DouList::push_front(const int &e) { if (m_head == NULL) { m_head = new DouListNode(e); m_tail = m_head; return; } DouListNode *temp = new DouListNode(e); temp->next = m_head; m_head->prev = temp; m_head = temp;}void DouList::push_back(const int &e) { if (m_tail == NULL) { m_tail = new DouListNode(e); m_head = m_tail; return; } DouListNode *temp = new DouListNode(e); temp->prev = m_tail; m_tail->next = temp; m_tail = temp;}void DouList::pop_front() { if (m_head == NULL) return; DouListNode *temp = m_head; m_head = m_head->next; if (m_head == NULL) { m_tail = NULL; delete temp; return; } m_head->prev = NULL; delete temp;}void DouList::pop_back() { if (m_tail == NULL) return; DouListNode *temp = m_tail; m_tail = m_tail->prev; if (m_tail == NULL) { m_head = NULL; delete temp; return; } m_tail->next = NULL; delete temp;}std::ostream& operator<<(std::ostream &out, const DouList &list) { out << list.to_str(); return out;}
下面是写这道题的过程中的一些记录,包括遇到的错误、心得体会、积累的经验等。
一直出现memory limit error的错误,用GDB检查它一直报clear()函数出现错误,可是实际上这个函数并没有问题,说明一定是其他原因导致了这个函数出现了错误,然后系统到这里才检测到。
经过查找,这次的原因,一个是在某些地方忘了把head和tail赋值为NULL,改完之后发现还是memory limit error,说明还有其他错误。最后发现是拷贝函数那里, DouList::DouList(const DouList &src) {*this = src;}
这个函数,忘了考虑如果src的head是NULL的话,我的重载 “=”是不会把this的head和tail给初始化为NULL的。
由此得到两个教训:
1、永远都要记得初始化成员变量,不管你是否需要用到。
2、一个函数直接调用另一个函数的时候要考虑到,这两个是否完全
等价,即是不是增加一些其他的条件。
比如这里的DouList::DouList(const DouList &src) {*this = src;}
“+”没有考虑到src的head是NULL,所以正确的应该是:
DouList::DouList(const DouList &src) { m_head = m_tail = NULL; *this = src;}//先初始化成员变量,谨慎一点。
至于一直MLE为什么GDB 报的是clear这个函数的问题:
void DouList::clear() { if (m_head != NULL) { DouListNode* p = m_head, *temp; while (p != NULL) { temp = p; p = p->next; delete temp; } m_head = m_tail = NULL; }}
这个函数中p = p->next;这一行的错误,发现原因之后很好解释:
如果main函数调用了DouList(const DouList &src)
函数,
如DouList list3(list1);
而list1又刚好是NULL,那就会出现head和tail没初始化的情况,自然很大程度上也不可能随机到NULL,所以clear的时候,因为p != NULL,所以继续进行下去,发现p = p->next,p根本没有next,所以在这里报错。
- 双向链表的一个简单的例子
- 一个简单的双向链表的例子
- 一个简单的双向链表
- 一个建立双向循环链表的例子
- 一个简单的双向循环链表的实现
- 一个比较(非常)简单的双向链表...
- 一个简单的例子
- 一个简单的双向链表类--xixi
- openmp 例子:一个简单的OpenMP例子
- 一个简单的Struts例子
- 一个简单的Hibernate例子!
- auto_ptr的一个简单例子
- 一个简单的Struts例子
- 一个简单的JSF例子
- 一个简单的EJB例子!!
- 一个简单的serverclick 例子
- 一个简单易懂的例子
- 一个GMF的简单例子
- Request常用方法
- Ubuntu 14.04环境变量修改
- Android开发中对象的实例化示例
- Swift-扩展
- lightoj 1079 Just another Robbery
- 一个简单的双向链表的例子
- 指针操作:【申请】、【释放】、【YUV2BGR】、【QT保存图像】
- uva1587 - Box
- C++基础:各种输入方法总结,cin、cin.get()、cin.getline()、getline()、gets()、getchar()
- 时间转换
- getOutputStream() has already been called for this response异常的原因和解决方法[转]
- 深入了解Object类
- springamqp的exchange
- Swift-协议