// // Created by Christian Gould on 9/15/20. // /* * Insertion sort adapted from professor Gabrielson's lecture materials */ #ifndef INC_20F_AUTO_IDX_LINKYLIST_H #define INC_20F_AUTO_IDX_LINKYLIST_H #define debug false #include "List.h" #include "Nody.h" #include "LinkyListIter.h" using namespace std; template<class t> // default will set the head and tail to null class LinkyList : public List<t> { private: Nody<t> *head; Nody<t> *tail; public: /* Iterator */ LinkyIter<t> begin () const { return LinkyIter<t> (this->head,0); } LinkyIter<t> end () const { return LinkyIter<t> (this->tail->getNext (),-1); } // default constructor makes sure the head and tail are null LinkyList () : List<t> () { this->head = nullptr; this->tail = nullptr; this->size = 0; } // this will make a deep copy of the head and tail of given LinkyList LinkyList (const LinkyList<t> &newGuy) : List<t> () { if (newGuy.head == nullptr && newGuy.tail == nullptr) { this->head = this->tail = nullptr; this-> size = newGuy.size; } else { for(int i = 0; i < newGuy.size; i++){ this->push_back(newGuy[i]); } } } // is using the above constructor when I want to use this one below. This is because it is actually a LinkyList<t> which I am trying to call constructor of LinkyList (const t& firstElem) : List<t> (){ this-> head = nullptr; this-> tail = nullptr; this-> size = 0; this-> push_back (firstElem); } // makes a deep copy using the = operator LinkyList& operator= (const LinkyList &newGuy){ // check if they are the same object if(*this != newGuy) { if (newGuy.head == nullptr && newGuy.tail == nullptr) { this->head = this->tail = nullptr; this-> size = 0; return *this; } else { if (this->head != nullptr){ delete this; } this->head = nullptr; this->tail = nullptr; this->size = 0; for(int i = 0; i < newGuy.size; i++){ this->push_back(newGuy[i]); } return *this; } } } // destructor ~LinkyList (){ // set the current to head Nody<t>* current = head; // while the current pointer is not nullptr / 0 while( current != 0) { // store the next pointer into the next variable Nody<t>* next = current->getNext(); // delete current delete current; // store that next pointer into the current variable current = next; } head = 0; } // will put the given element into the back of the linked list void push_back (const t& pushMe){ // if there are no elements set head to tail to the only element if (this-> size == 0) { head = tail = new Nody<t> (pushMe); this->size = 1; } else { // if there are elements, add it at the end tail->setNext (new Nody<t> (pushMe)); tail->getNext()->setPrev (tail); this-> tail = tail->getNext (); this->size++; } } void push_front (const t& pushMe){ // if there are not elements, make it the only element if (head == nullptr){ head =tail = new Nody<t> (pushMe); this-> size = 1; } else { // if there are elements, add it to the front Nody<t>* temp = head; this-> head = new Nody<t> (pushMe); head->setNext(temp); temp->setPrev (head); this-> size++; } } // returns an iterator to the given parameter in the vector, and if not found, returns .end() LinkyIter<t> find(t findMe){ LinkyIter<t> returnMe = this->begin(); for(returnMe; returnMe != this->end(); ++returnMe){ if(*returnMe == findMe) break; } // return the iterator return returnMe; } // will return the payload of the wanted element in the list t& operator[] (int iWant) const{ int incrementor = 0; Nody<t> *temp = this->head; while (incrementor < iWant && temp != this->tail) { temp = temp->getNext (); incrementor++; } return temp->getPayload (); } Nody<t>* findNode(int find) const { Nody<t>* current = this-> head; int counter = 0; while(counter < find && current != tail){ current = current->getNext(); counter++; } return current; } // this will remove the given element in the list void remove (int removeMe) { if(debug)cout << "size before removal: " << this-> size << endl; // removing from the beginnning if (removeMe == 0) { // if there are more than 2 elements if (this->size > 2) { Nody<t>* deleteMe = this->head; this->head = this->head->getNext (); delete deleteMe; // if there is only 1 element } else if (this->size == 1) { delete this-> head; this->head = this->tail = nullptr; // if there is 2 elements } else if (this->size == 2) { Nody<t>* gone = this->head; this->head = this->head->getNext (); this->tail = this->head; this-> head->setPrev (nullptr); this->tail->setPrev (nullptr); delete gone; } } else // removing from the middle if (removeMe > 0 && removeMe < this->size - 1) { Nody<t>* currptr = head; int i = 0; while (currptr != tail && i < removeMe - 1) { currptr = currptr->getNext (); i++; } // prev is the element before the one being removed. Nody<t> *prev = currptr; Nody<t> *toDelete = currptr->getNext (); Nody<t> *next = toDelete->getNext (); prev->setNext (next); next->setPrev (prev); delete toDelete; } else // removing from the end if (removeMe == this->size - 1) { if(this->size <= 1){ this->head = this->tail = nullptr; return;} Nody<t> *currptr = head; delete tail; tail = tail->getPrev (); tail->setNext (nullptr); } // reduce size by one because we have removed an element this->size--; if(debug)cout << "size after removal: " << this-> size << endl; } // this will return the size of the linked list // int getSize () const { // return this->size; // } // function which will find the size of the linked list if there are problems int findSize() const { // // if there are no elements in the list if (this->head == nullptr) { return 0; } // if there is only one element in the list if (this->head == this->tail) return 1; // if there is more than one element in the list Nody<t> *temp = this->head; int size = 1; while (temp != this->tail) { temp = temp->getNext (); size++; } return this->size; } // replaces one element in the Linked list void replace (int toRepl, t newGuy){ int i = 0; Nody<t>* temp = head; // get the element to be replaced while(i < toRepl && temp != tail){ temp = temp->getNext (); i++; } delete temp->getPayloadptr (); temp->setPayload (new t(newGuy)); } void insertionSort(){ int thisSizey = this->size ; // this integer is a counter for each element in the array int i; // this integer is a counter for the index of the current element being sorted int j; // temporary variables to swap t temp; t tempmin; for (i = 1; i < thisSizey; ++i) { // set the index to be checked to i j = i; // Insert yvector[i] into sorted part // stopping once yvector[i] in correct position while (j > 0 && (this->operator[] (j)) < (this->operator[](j - 1))) { Nody<t>* nodeJ = this->findNode(j); Nody<t>* nodeJmin = this->findNode (j-1); temp = nodeJ->getPayload(); tempmin = nodeJmin->getPayload(); delete nodeJ->getPayloadptr (); delete nodeJmin->getPayloadptr(); nodeJ->setPayload (tempmin); nodeJmin->setPayload (temp); --j; } } this->sorted = true; } /* Operators */ bool operator==(const LinkyList<t>& rhs) const{ LinkyIter<t> leftIter = begin(); LinkyIter<t> rightIter = rhs.begin(); // if the sizes are the same if(this->size == rhs.size){ // loop through all the elements while(leftIter != end()){ // if they are not the same, then return false if(*leftIter != *rightIter) { if(debug) cout << "wrong by wrong thing" << endl; return false; } if(debug)cout << "left: " << *leftIter << endl; if(debug)cout << "right: " << *rightIter << endl; ++leftIter; ++rightIter; } return true; } // if they are not the same size, return false else { if(debug)cout << "wrong by size" << endl; return false; } } friend bool operator<(const LinkyList<t>& lhs, const LinkyList<t>& rhs){ return lhs.size < rhs.size; } bool operator != (const LinkyList<t>& rhs){ return !((*this) == rhs); } friend ostream& operator<< (ostream& OS, const LinkyList<t>& rhs){ for(int i = 0; i < rhs.size; i++){ OS << (rhs)[i] << " "; } } }; #endif //INC_20F_AUTO_IDX_LINKYLIST_H