SSD5_Optional Exercise 1 分析
这个题主要考察对继承的掌握
还有动态存储和异常处理
按照步骤一步步来做这个题
Extract the archive to retrieve the files needed to complete this assessment
我们得到LinkedList.h,我还给了相应的注释
#ifndef _LINKEDLIST_H_ #define _LINKEDLIST_H_ #include <stdexcept> /* * 作者:白强 * 日期:2013/4/18 * 这是题目给的一个数据结构实现 * 它可以在链尾或链头插入和删除元素 * virtual void push_front(T); // Insert element at beginning virtual void push_back(T); // Insert element at end virtual void pop_front(void); // Remove element from beginning virtual void pop_back(void); // Remove element from end virtual void dump(void); // Output contents of list * 三个变量 * Node<T>* head; // Beginning of list Node<T>* tail; // End of list int count; // Number of nodes in list * */ using namespace std; //List为空抛出异常的类定义 class EmptyListException : public logic_error { public: EmptyListException(const string& what_arg ) throw() : logic_error ("Empty list exception: " + what_arg) {}} ; //定义节点类 template <typename T> class Node { private: //数据和指针 T data; Node* next; public: Node(T d, Node* n = NULL) : data(d), next(n) {} T& getData() { return data; } Node*& getNext() { return next; } }; //链表类 template <typename T> class LinkedList { protected: Node<T>* head; // Beginning of list Node<T>* tail; // End of list int count; // Number of nodes in list public: LinkedList(void) : head(NULL), tail(NULL), count(0) {} LinkedList(const LinkedList<T>& src); // Copy constructor virtual ~LinkedList(void); // Destructor //得到链头元素,为空则抛出异常 virtual T& front(void) { if (head == NULL) { throw EmptyListException("front()"); } return head->getData(); } //得到链尾元素,为空则抛出异常 virtual T& back(void) { if (tail == NULL) { throw EmptyListException("back()"); } return tail->getData(); } //得到链表的长度 virtual int size(void) { return count; } //制空链表 virtual bool empty(void) { return count == 0; } //四个主要的方法 virtual void push_front(T); // Insert element at beginning virtual void push_back(T); // Insert element at end virtual void pop_front(void); // Remove element from beginning virtual void pop_back(void); // Remove element from end //输出函数 virtual void dump(void); // Output contents of list }; // Copy constructor //拷贝构造函数,注意深拷贝 template <typename T> LinkedList<T>::LinkedList(const LinkedList<T>& src) : head(NULL), tail(NULL), count(0) { Node<T>* current = src.head; while (current != NULL) { this->push_back(current->getData()); current = current->getNext(); } } //析构函数,不为空则依次删除链头元素 template <typename T> LinkedList<T>::~LinkedList(void) { while (!this->empty()) { this->pop_front(); } } //链头插入 // Insert an element at the beginning template <typename T> void LinkedList<T>::push_front(T d) { Node<T>* new_head = new Node<T>(d, this->head); //如果是空表 if (this->empty()) { //链头和链尾当然都是它了 this->head = new_head; this->tail = new_head; } else { //一般情况下它应该是链头 this->head = new_head; } this->count++; } //链尾插入 // Insert an element at the end template <typename T> void LinkedList<T>::push_back(T d) { Node<T>* new_tail = new Node<T>(d, NULL); if (this->empty()) { this->head = new_tail; } else { //当前的链尾的下一个就是这个元素了 this->tail->getNext() = new_tail; } this->tail = new_tail; this->count++; } //链头删除 // Remove an element from the beginning template <typename T> void LinkedList<T>::pop_front(void) { if (this->head == NULL) { throw EmptyListException("pop_front()"); } Node<T>* old_head = head; if (this->size() == 1) { //只剩一个的时候再把这个给删了,则链头链尾都为NULL了 this->head = NULL; this->tail = NULL; } else { //一般情况链头应该是old_head的下一个元素 this->head = this->head->getNext(); } //删除链头元素并减少元素个数 delete old_head; this->count--; } //链尾删除和链头差不多。相信你懂了 // Remove an element from the end template <typename T> void LinkedList<T>::pop_back(void) { if (this->tail == NULL) { throw EmptyListException("pop_back()"); } Node<T>* old_tail = this->tail; if (this->size() == 1) { this->head = NULL; this->tail = NULL; } else { // Traverse the list Node<T>* current = this->head; while (current->getNext() != this->tail) { current = current->getNext(); } // Unlink and reposition current->getNext() = NULL; this->tail = current; } delete old_tail; this->count--; } //迭代输出链表的元素 // Display the contents of the list template <typename T> void LinkedList<T>::dump(void) { cout << "("; if (this->head != NULL) { Node<T>* current = this->head; while (current->getNext() != NULL) { cout << current->getData() << ", "; current = current->getNext(); } cout << current->getData(); } cout << ")" << endl; } #endif
这时题目要求是
Declare your class EnhancedLinkedList in a header file EnhancedLinkedList.h. Class EnhancedLinkedList should be a template class. Use inheritance appropriately to model the following relationship: class EnhancedLinkedList is a type of LinkedList.
那我们就来写个加强版的链表吧
它给把方法都介绍了
- Next, implement member function find_first. Use the following prototype to declare this member function:
T& find_first (const T& key);
Method find_first should search the EnhancedLinkedList for the first occurrence of an item that matches the value in the parameter key. It should return a reference to the first matching item. If the invoking EnhancedLinkedList object is empty or no item is found that matches the parameter, a ListItemNotFoundException should be thrown. You will have to define this exception (Hint: define this exception much the same way that the EmptyListException exception is defined in LinkedList.h).
- Then, implement member function find_all. Use the following prototype to declare this member function:
EnhancedLinkedList find_all (const T& key);
Method find_all should search the invoking EnhancedLinkedList for all elements that match the value in the parameter key. It should return an EnhancedLinkedList object containing copies of all the items that match the parameter key. If the invoking EnhancedLinkedList object is empty or no item is found that matches the parameter, this function should return an empty EnhancedLinkedList.
- Next, implement member function remove_first. Use the following prototype to declare this member function:
void remove_first (const T& key);
Method remove_first should remove the first element from the invoking EnhancedLinkedList whose data item matches the parameter key. If the invoking EnhancedLinkedList object is empty or no item is found that matches the parameter, this function should do nothing. Remember to leave no memory leaks.
- Finally, implement member function remove_all. Use the following prototype to declare this member function:
void remove_all (const T& key);
Method remove_all should remove all elements from the invoking EnhancedLinkedList whose data items match the parameter key. If the invoking EnhancedLinkedList object is empty or no item is found that matches the parameter, this function should do nothing. Remember to leave no memory leaks.
我们要实现上述方法,注意还要抛出异常,下面j就是EnhancedLinkedLish.h
#ifndef EnhancedLinkedList_H #define EnhancedLinkedList_H #include <iostream> #include <stdexcept> #include "LinkedList.h" using namespace std; /* * 作者:白强 * 日期:2013/4/18 * 这是一个加强版的LinkedList * 它可以在链尾或链头插入和删除元素并抛出异常 * 四个方法 EnhancedLinkedList(void); virtual T& find_first(const T& key); virtual EnhancedLinkedList<T> find_all(const T& key); virtual void remove_first(const T& key); virtual void remove_all(const T& key); * */ //元素找不到抛出异常类定义 class listItemNotFoundException:public logic_error { public: listItemNotFoundException(const string& what_arg) throw() : logic_error("List item not found execption:"+what_arg){} }; //EnhancedLinkedList继承自LinkedList<T> template <class T> class EnhancedLinkedList : public LinkedList<T> { public: EnhancedLinkedList(void); virtual T& find_first(const T& key); virtual EnhancedLinkedList<T> find_all(const T& key); virtual void remove_first(const T& key); virtual void remove_all(const T& key); }; //默认构造函数 template <class T> EnhancedLinkedList<T>::EnhancedLinkedList(void) { } /* * 如何找到第一个匹配的元素并返回 * 显示判断这个链表的链头是不是空的,是空的的话直接抛出找不到的异常 * 不是的话用迭代匹配第一个 * */ template <class T> T& EnhancedLinkedList<T>::find_first(const T& key) { if(this->head != NULL) { Node<T>* current = this->head; for(;current->getNext() != NULL;current = current->getNext()) { if(current->getData() == key) { //只要一找到匹配的元素就跳出循环并返回该元素 break; } } return (T&)*current; } else { throw listItemNotFoundException("find_first()"); } } /* * 这个find_all方法要求返回一个EnhancedLinkedList对象 * 所以它会把所有匹配的元素找出并调用从基类继承来的函数加入到EnhancedLinkedList中去 */ template <class T> EnhancedLinkedList<T> EnhancedLinkedList<T>::find_all(const T& key) { EnhancedLinkedList<T> temp; if(this->head!= NULL) { Node<T> *current = this->head; for(;current->getNext() != NULL;current = current->getNext()) { if(current->getData() == key) { temp.push_back(current->getData()); } } } return temp; } /* * 删除的时候注意要判断元素的位置 * 在链头和链尾不能一概而论 */ template<class T> void EnhancedLinkedList<T>::remove_first (const T& key)//我想在删除的时候判断是否在队头或队尾 { if(this->head!=NULL) { Node<T>* current=this->head; Node<T>* tem; int temp=0; //如果在链头 if(this->head->getData()==key) { temp=1; } if(temp==0) { //如果在链尾 if(this->tail->getData()==key) { temp=2; } } if(temp==0) { //如果在链表中间 for(;current->getNext()!=NULL;current=current->getNext()) { if(current->getNext()->getData()==key) { temp=3; tem=current; } } } //如果在链头,则删除第一个元素即可 if(temp==1) { this->pop_front(); } //如果在链尾,则删除最后一个元素即可 else if(temp==2) { this->pop_back(); } //在链表中间主要就是把这个元素架空,和一般的链表一样,然后删除之 else if(temp==3) { Node<T>*tem1=tem->getNext(); tem->getNext()=tem->getNext()->getNext(); delete tem1; this->count--; } } } //这个删除全部匹配的就不介绍了,其实也一样 template<class T> void EnhancedLinkedList<T>::remove_all (const T& key) { int temp = 0; for(Node<T>* current =this-> head;current != NULL;current = current->getNext()) { if(current->getData() == key) { temp++; } } for(int i = 0;i<temp;i++) { remove_first(key); } } #endif
最后附上它的测试文件
// For Visual C++ users: // Visual C++ does not implement checked exceptions, and the compiler will // show warning messages when functions throws exceptions. The following // warning pragma ignore those compiler messages. // // GCC users can remove this #pragma warning. //#pragma warning(disable: 4290) /*这个是它给的测试文件testdriver.cpp,简单给说明一下 * 注释:白强 * 日期:2013/4/18 */ #include <iostream> #include <cstdlib> #include <string> #include <stdexcept> #include "EnhancedLinkedList.h" using namespace std; int main (int argc, char* argv[]) { //创建对象 EnhancedLinkedList<string> master; master.push_back ("one"); master.push_back ("two"); master.push_back ("three"); master.push_back ("four"); master.push_back ("five"); { cout << "Find with empty list: This test should indicate not found exception" << endl; EnhancedLinkedList<string> l; //要找到not there 肯定会抛出异常的 try { l.find_first("not there"); } catch (logic_error& e) { cout << e.what() << endl; } cout << endl; } { cout << "Looking for non existent item: This test should indicate not found exception" << endl; EnhancedLinkedList<string> l(master); try { l.find_first("not there"); } catch (logic_error& e) { cout << e.what() << endl; } cout << endl; } { cout << "Looking for first item: This test should indicate found" << endl; //通过拷贝构造函数创建对象 EnhancedLinkedList<string> l(master); //这下肯定找到了 try { string got = l.find_first("one"); cout << "found" << endl; } catch (logic_error& e) { cout << e.what() << endl; } cout << endl; } /* * find last: find last item */ { cout << "Looking for last item: This test should indicate found" << endl; EnhancedLinkedList<string> l(master); try { string got = l.find_first("five"); cout << "found" << endl; } catch (logic_error& e) { cout << e.what() << endl; } cout << endl; } //下面就自己看吧,很好懂的 /* * find in middle: find an item in middle */ { cout << "Looking for middle item: This test should indicate found" << endl; EnhancedLinkedList<string> l(master); try { string got = l.find_first("three"); cout << "found" << endl; } catch (logic_error& e) { cout << e.what() << endl; } cout << endl; } /* * find all, including head and tail */ { cout << "Looking for three 'magic' items: Should print 'magic' three times" << endl; EnhancedLinkedList<string> l; l.push_back ("magic"); l.push_back ("one"); l.push_back ("two"); l.push_back ("three"); l.push_back ("magic"); l.push_back ("four"); l.push_back ("five"); l.push_back ("magic"); LinkedList<string> got = l.find_all("magic"); got.dump(); cout << endl; } /* * remove first on empty list */ { cout << "Removing item from empty list: " << endl; EnhancedLinkedList<string> l; l.remove_first("not in list"); if (0 == l.size()) { cout << "success" << endl; } else { cout << "failure" << endl; } cout << endl; } /* * remove first, including head and tail */ { cout << "Removing item from list that does not contain item: " << endl; EnhancedLinkedList<string> l(master); l.remove_first("not in list"); if (5 == l.size()) { cout << "success" << endl; } else { cout << "failure" << endl; } cout << endl; } /* * remove first item from list */ { cout << "Removing first item from list: " << endl; EnhancedLinkedList<string> l(master); l.remove_first("one"); if (4 == l.size()) { cout << "Should be (two, three, four, five):" << endl; l.dump(); } else { cout << "failure" << endl; } cout << endl; } /* * remove last item from list */ { cout << "Removing last item from list: " << endl; EnhancedLinkedList<string> l(master); l.remove_first("five"); if (4 == l.size()) { cout << "Should be (one, two, three, four):" << endl; l.dump(); } else { cout << "failure" << endl; } cout << endl; } /* * remove last item from list */ { cout << "Removing middle item from list: " << endl; EnhancedLinkedList<string> l(master); l.remove_first("three"); if (4 == l.size()) { cout << "Should be (one, two, four, five):" << endl; l.dump(); } else { cout << "failure" << endl; } cout << endl; } /* * remove last item from list */ { cout << "Removing all on empty list: " << endl; EnhancedLinkedList<string> l; l.remove_all("three"); if (0 == l.size()) { cout << "success" << endl; } else { cout << "failure" << endl; } cout << endl; } /* * remove last item from list */ { cout << "Removing all on list, should print (one, two, three, four, five): " << endl; EnhancedLinkedList<string> l; l.push_back ("magic"); l.push_back ("one"); l.push_back ("two"); l.push_back ("three"); l.push_back ("magic"); l.push_back ("four"); l.push_back ("five"); l.push_back ("magic"); l.remove_all("magic"); l.dump(); } return EXIT_SUCCESS; }
这个题就完成了,只是实现一个加强版的链表而已