數據結構:參數化循環鏈表的C++實現(實現異常捕獲)

題目描述:

Create in C ++, a parametric class MyCircularList <T>. The objects of MyCircularList <T> are sets of objects of type (class) Node <T>, each node pointing to the next one and to the previous one. In a circular list the next node at the last node is the first node (reference node) and the node before the first node is the last node.

1.     The class Nœud<T> must have a member  « data » of type T and two pointers of type Node<T>*. It must also have a private constructor with signature:

Node(T v)

which creates a node with data = v and pointers set to nullptr. The Node <T> class must declare the MyCircularList <T> and MyCircularIterator <T> classes as friends.

2.     The MyCircularList <T> class must be public, with a private field: the "_head" field for the head of the list (the reference node). The MyCircularList <T> class must declare the MyCircularIterator <T> class as friend. The MyCircularList <T> class must have 3 public constructors with signatures:
 

MyCirculaireList() // empty list  (_head = nullptr)

MyCirculaireList(T v) // list of a single node whose field « data » is v.

MyCirculaireList(T v []) // list whose nodes correspond to the elements of the array v 

It must also have the dynamical methods: 
 

public Vector<T> toVector() // returns the vector of objects of type T

   //corresponding to the MyCirculaireList.

public MyCirculaireList<T> copy()  // returns a copy (clone) of MyCirculaireList.

public T head() // returns the value of « data » of the node pointed by _head (nœud de référence)

public void append (T e) // creates a node with « data »=e at the "end" of the MyCirculaireList.

public void concat (MyCirculaireList<T> lc) // concatenates a copy of lc at the "end" of the MyCirculaireList.

public MyCirculaireListIterator<T> iterator() // method to initialise the iterator 

   //MyCirculaireListIterator for the object

   //current MyCirculaireList  

3.     The MyCircularListIterator <T> class must have two private fields (pointers), for example:
 

Node<T>* current; // current node 

MyCircularList<T>* ch; // Instance of MyCircularList on which we iterate. 

The MyCircularListIterator <T> class must declare the MyCircularList <T> class as a friend. The MyCircularListIterator <T> class must also have a constructor with signature:

public MyCircularListIterator(MyCircularList<T> a) 

(If the instance of MyCircularList on which we iterate is not empty, the current pointer will indicate the node which precedes the reference node, _head, of ch, otherwise current is nullptr.)

and the dynamic methods:

public bool isEmpty()  // checks if the instance of MyCircularList on which we  

                    // iterate is empty vide

public T next() // moves the pointer current to the next node and  returns its

            // value

public T previous() // returns the value of the node pointed by current and moves the

               // pointer current to the preceding node

public bool isAtBegin() // check if current points to the node that precedes

                  // the reference node (_head)  

public void goToBegin()    // moves the pointer current to its initial position.

public void set (T v )      // assign v as the value of « data » of the node pointed by   

  // current.

4.     The classes MyCircularList <T> and MyCircularListIterator <T> must use an exception class MCLInvalidAccessException, extension of exception class, which must receive a numeric parameter to identify (at least) the six exception cases:
 

  case 1 : msg= "Invalid head() call: empty list";

  case 11 : msg= "Invalid next() call: empty list";

  case 12: msg = "Invalid previous() call: empty list";

  case 13: msg = "Invalid isAtBegin() call: empty list";

  case 14: msg = "Invalid goToBegin() call: empty list";

  case 15: msg = "Invalid set(T v) call: empty list";

Attention : You should also write a C ++ "main" program to check if your classes are working well (informal test).

 

代碼實現:

#include <iostream>
#include <vector>
#include <exception>
using namespace std;

//喬卿
//2020-06-21

template<class T>
class Node {
	public:
		T val;
		Node *next;
		Node *pre;

		Node(T v) {
			val = v;
			next = NULL;
			pre = NULL;
		}
};

class MCLInvalidAccessException: public exception {
	public:
		const char * what (int id) const throw () {
			switch(id) {
				case 1:
					return "Invalid head() call: empty list";
					break;
				case 11:
					return "Invalid next() call: empty list";
					break;
				case 12:
					return "Invalid previous() call: empty list";
					break;
				case 13:
					return "Invalid isAtBegin() call: empty list";
					break;
				case 14:
					return "Invalid goToBegin() call: empty list";
					break;
				case 15:
					return "Invalid set(T v) call: empty list";
					break;
			}
		}

};


template <typename T> class MyCirculaireListIterator;
template <typename T> class MyCircularList {

	private:
		Node<T>* _head;
		friend class MyCirculaireListIterator<T>;

	public:
		MyCircularList<T>() {
			_head=NULL;
		}

		MyCircularList(T v) {
			_head=new Node<T>(v);
		}

		MyCircularList(T v []) {
			_head=new Node<T>(v[0]);
			int len=(sizeof(v) / sizeof(v[0]));
			for(int i=1; i<len; i++) {
				append(v[i]);
			}
		}

		vector<T> toVector() {
			vector<T> rs;
			Node<T>* now=_head;
			if(_head==NULL) {
				return rs;
			}
			rs.push_back(_head->val);
			now=_head->next;
			while(now!=_head) {
				rs.push_back(now->val);
				now=now->next;
			}
			return rs;
		}

		MyCircularList<T> copy() {
			MyCircularList<T> copy;
			if(_head==NULL) {
				return copy;
			}
			copy.append(_head->val);
			Node<T> * curr=_head->next;
			while(curr!=_head) {
				copy.append(curr->val);
				curr=curr->next;
			}
			return copy;
		}

		void append(T e) {
			if(_head==NULL) {
				_head=new Node<T>(e);
				_head->next= _head;
				_head->pre= _head;
			} else {
				Node<T>* tail=new Node<T>(e);
				tail->next=_head;
				Node<T>* curr=_head;
				while(curr->next!=_head) {
					curr=curr->next;
				}
				curr->next=tail;
			}
		}

		void concat (MyCircularList<T> lc) {
			Node<T>* curr=_head;
			while(curr->next!=_head) {
				curr=curr->next;
			}
			curr->next=lc._head;

			Node<T>* curr2=lc._head;
			while(curr->next!=lc._head) {
				curr=curr->next;
			}
			curr->next=_head;
		}

};



template <typename T> class MyCirculaireListIterator {

	private:
		Node<T>* current=NULL;
		MyCircularList<T>* ch=NULL;
		friend class MyCircularList<T>;

	public:
		MyCirculaireListIterator() {

		}

		MyCircularListIterator(MyCircularList<T> a)  {
			ch=&a;
			current=a._head;
		}

		bool isEmpty() {
			return (current==NULL) || (ch==NULL);
		}

		T head() {
			try {
				if(ch==NULL)
					throw MCLInvalidAccessException();
				return ch->_head;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(1);
			}
		}

		T next() {
			try {
				if(current==NULL)
					throw MCLInvalidAccessException();
				current=current->next;
				return current->val;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(11);
			}
		}

		T previous() {
			try {
				if(current==NULL)
					throw MCLInvalidAccessException();
				current=current->pre;
				return current->val;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(12);
			}
		}

		bool isAtBegin() {
			try {
				if(current==NULL || ch==NULL)
					throw MCLInvalidAccessException();
				return current==ch->_head;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(13);
			}


		}

		void goToBegin() {
			try {
				if(ch==NULL)
					throw MCLInvalidAccessException();
				current=ch->_head;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(14);
			}

		}

		void set(T v) {
			try {
				if(current==NULL)
					throw MCLInvalidAccessException();
				current->val=v;
			} catch (MCLInvalidAccessException& e) {
				cout<<e.what(15);
			}
		}
		
		void setCh(MyCircularList<T> a) {
			ch=&a;
			current=a._head;
		}

};

int main() {
        //喬卿
        //2020-06-21

	//create my list
	MyCircularList<int> list;
	//append
	list.append(1);
	list.append(2);
	list.append(3);
	//show	
	vector<int> v0=list.toVector();
	
	for(int i = 0; i < v0.size(); i++) {
		cout<<v0[i];
	}
	cout<<endl;
	//append
	list.append(4);
	//show
	vector<int> v1=list.toVector();
	for(int i = 0; i < v1.size(); i++) {
		cout<<v1[i];
	}
	cout<<endl;
	//create my iterator
	MyCirculaireListIterator<int> itor;
	itor.setCh(list);
	itor.goToBegin();
	itor.set(9);
	vector<int> v2=list.toVector();
	for(int i = 0; i < v2.size(); i++) {
		cout<<v2[i];
	}
	cout<<endl;	
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章