230 likes | 242 Views
List as an Abstract Data Type. struct Node{ public: int data; Node* next; }; typedef Node* Nodeptr; class List { public: List(); // constructor List(const list& list1); // copy constructor ~List(); // destructor
E N D
struct Node{ public: int data; Node* next; }; typedef Node* Nodeptr; class List { public: List(); // constructor List(const list& list1); // copy constructor ~List(); // destructor bool empty() const; // boolean function int headElement() const; // access functions void addHead(int newdata); // add to the head void delHead(); // delete the head int length() const; // utility function void print() const; // output private: Nodeptr head; };
How to use it int i(0); Int j(10); Int k(j); void main(){ List L; // constructor called automatically here for L L.print(); { } L.addHead(30); L.print(); { 30 } L.addHead(13); L.print(); { 13 30 } L.addHead(40); L.print(); { 40 13 30 } L.addHead(50); L.print(); { 50 40 13 30 } List N(L); N.print(); { 50 40 13 30 } List R; R.print(); { } if(R.empty()) cout << "List R empty" << endl; L.delHead(); L.print(); { 40 13 30 } L.delHead(); L.print(); { 13 30 } if(L.empty()) cout << "List L empty" << endl; else{ cout << "List L contains " << L.length() << " nodes" << endl; cout << "Head element of list L is: " << L.headElement() << endl; } } // destructor called automatically here for L
Motivation • list using static array int myArray[1000]; int n; We have to decide (to oversize) in advance the size of the array (list) • list using dynamic array int* myArray; int n; cin >> n; myArray = new int[n]; We allocate an array (list) of any specified size while the program is running • linked-list (dynamic size) size = ?? The list is dynamic. It can grow and shrink to any size.
struct Node{ public: int data; Node* next; }; typedef Node* Nodeptr; class List { public: List(); // constructor List(const List& list1); // copy constructor ~List(); // destructor bool empty() const; // boolean function int headElement() const; // access functions void addHead(int newdata); // add to the head void delHead(); // delete the head int length() const; // utility function void print() const; // output private: int head[10000]; int size; }; Or int head[DIM]; int size; cont int DIM=10000;
Implementation Some simple member functions: List::List(){ head = NULL; size = 0; } bool List::empty() const{ if(head==NULL) return true; else return false; } int List::headElement() const { if(head != NULL) return head->data; else{ cout << "error: trying to find head of empty list" << endl; exit(1); } } If (size==0) return true; else return false; If (size!=0) return head[0]; else …;
(explicitly defined) copy constructor: List::List(const list& list1) { head = NULL; Nodeptr cur = list1.head; while(cur != NULL) { // addEnd(cur->data); addHead(cur->data); // inverse list order cur = cur->next; } } If (list1.size!=0) for (int i=0; i<list1.size; i++) head[i]=list1.head[i];
Destructor: deallocation function List::~List(){ Nodeptr cur; while(head!=NULL){ cur = head; head = head->next; delete cur; } } Nothing here as it’s static.
Adding an element to the head: void List::addHead(int newdata){ Nodeptr newPtr = new Node; newPtr->data = newdata; newPtr->next = head; head = newPtr; } If (size<10000) { for (int i=size; i>=;i--) head[i+1]=head[i]; head[0]=newdata; size++; }
Deleting the head: void List::delHead(){ if(head != NULL){ Nodeptr cur = head; head = head->next; delete cur; } } for (int i=1; i<size;i++) head[i-1]=head[i]; size--;
Print the list: void List::print() const{ cout << "{"; Nodeptr cur = head; while(cur != NULL){ cout << cur->data << " "; cur = cur->next; } cout << "}" << endl; } for (int i=0; i<size;i++) cout << head[i];
Computing the number of elements of a given list: int List::length() const{ int n=0; Nodeptr cur = head; while(cur != NULL){ n++; cur = cur->next; } return n; } return size;
struct Node{ public: int data; Node* next; }; typedef Node* Nodeptr; class List { public: List(); // constructor List(const List& list1); // copy constructor ~list(); // destructor bool empty() const; // boolean function int headElement() const; // access functions void addHead(int newdata); // add to the head void delHead(); // delete the head int length() const; // utility function void print() const; // output private: int* head; int size; };
Implementation Some simple member functions: List::List(){ … } bool List::empty() const{ } int List::headElement() const { }
(explicitly defined) copy constructor: List::List(const List& list1) { }
Other functions … List::~List(){ delete[] head; }
Conclusion: the usage is the same!!! No matter it is linked list, static array or dynamic array! void main(){ List L; // constructor called automatically here for L L.print(); { } L.addHead(30); L.print(); { 30 } L.addHead(13); L.print(); { 13 30 } L.addHead(40); L.print(); { 40 13 30 } L.addHead(50); L.print(); { 50 40 13 30 } List N(L); N.print(); { 50 40 13 30 } List R; R.print(); { } if(R.empty()) cout << "List R empty" << endl; L.delHead(); L.print(); { 40 13 30 } L.delHead(); L.print(); { 13 30 } if(L.empty()) cout << "List L empty" << endl; else{ cout << "List L contains " << L.length() << " nodes" << endl; cout << "Head element of list L is: " << L.headElement() << endl; } } // destructor called automatically here for L
template<typename T> class List { public: List(); // constructor List(const List& list1); // copy constructor ~list(); // destructor bool empty() const; // boolean function int headElement() const; // access functions void addHead(T newdata); // add to the head void delHead(); // delete the head int length() const; // utility function void print() const; // output private: T* head; int size; };
Implementation Some simple member functions: template<typename T> List::List(){ head=NULL; size=0; } template<typename T> bool List::empty() const{ } template<typename T> T List::headElement() const { }
Other functions … template<typename T> List::~List(){ delete T[] head; }