/ Published in: C++
This is a linked list that can be used like an array where instead of using [] after the reference you just used .get() (and some other methods) but now you don't have to worry about sizing.
For example, with an array you would do:
cout
For example, with an array you would do:
cout
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
/*######################################################### HEADER FILE "linked_list.h": ###########################################################*/ /* Joe Pea - Linked List */ #ifndef LINKED_LIST_H #define LINKED_LIST_H #include <cstdlib> // Provides size_t #include "node.h" // Provides node class namespace CISP430_A5 { template <class Item> class linked_list /*TODO: * Optimize so that we don't have to iterate through each address to reach a desired position. Make a "position" field for each Node object or something? Or create a "last_position" variable in this class so we can iterate forward or backward from the last position instead of from the beginning each time? * Add post and pre conditions for all the new functions above. */ /** The /*REMOVED*//*, /*STAYS THE SAME*//*, and /*ADDED*//* comments show the differences in converting from the sequence class to the linked_list class. */ { public: /* TYPEDEFS and MEMBER CONSTANTS: */ typedef Item value_type; typedef size_t size_type; /* CONSTRUCTORS and DESTRUCTOR: */ linked_list( ); linked_list(const linked_list& source); ~linked_list( ); /* MODIFICATION MEMBER FUNCTIONS */ /*ADDED:*/ value_type get(int position); // get item at position x void set(int position, const value_type& entry); // set item at position x, if past boundaries, just modify at beginning or at end. void add(const value_type& entry); // add to the end of list void insert(int position, const value_type& entry); // set item at position x, if past boundaries, just insert at beginning or attach at end. void attach(int position, const value_type& entry); // set item at position x, if past boundaries, just insert at beginning or attach at end. void remove(int position); /*REMOVED:*/ /*void remove_current( );*/ /*void start( );*/ /*void advance( );*/ /*void insert(const value_type& entry);*/ /*void attach(const value_type& entry);*/ /*STAYS THE SAME:*/ void operator=(const linked_list& source); /* CONSTANT MEMBER FUNCTIONS */ /*STAYS THE SAME:*/ value_type current( ) const; size_type size( ) const { return many_nodes; } bool is_item( ) const { return (cursor != NULL); } private: /*PRIVATE HELPER FUNCTIONS*/ /*ADDED:*/ void remove_current( ); void start( ); void advance( ); void insert_here(const value_type& entry); // same as insert() from sequence. insert at current position. void attach_here(const value_type& entry); // same as attach() from sequence. attach at current position. /*PRIVATE VARIABLES*/ /*STAYS THE SAME:*/ node<Item> *cursor; node<Item> *precursor; node<Item> *head_ptr; node<Item> *tail_ptr; size_type many_nodes; }; } /* Sample usage: int main(void) { linked_list items = new linked_list; items.attach(10); items.insert(30); items.attach(20); items.insert(40); // for each item in the list: for (int i=0; i<items.size(); ++i) { cout << items.get(i) << endl; } items.set(2, 50); // item at position 2 is now 50. } */ // The implementation of a template class must be included in its header file: #include "linked_list.template" #endif /*######################################################### TEMPLATE FILE "linked_list.template": ###########################################################*/ /* Joe Pea - CISP430 Assignment 5 */ namespace CISP430_A5 { /*I've marked lines/blocks as REMOVED or ADDED in order to tell what I changed from the sequence class to create my ideal linked_list class*/ /*TODO: Add previous field to Node class and remove usage of precursor.*/ /* CONSTRUCTORS and DESTRUCTOR */ template <class Item> linked_list<Item>::linked_list() { head_ptr = NULL; tail_ptr = NULL; cursor = NULL; precursor = NULL; // no need for this if Node objects have a "previous" link field. many_nodes = 0; } template <class Item> linked_list<Item>::linked_list( const linked_list& source ) { // copier int src_size = source.size(); // to replicate cursor position int many_til_end = 0; // to replicate cursor position int many_til_mid = 0; // to replicate cursor position node<Item> *src_cursor = source.cursor; // to replicate cursor position list_copy(source.head_ptr, head_ptr, tail_ptr); /*replicate the size value (before cursor position because functions used for that depend on many_nodes value*/ many_nodes = source.many_nodes; /*replicate the cursor position*/ if (src_cursor != NULL) { while (src_cursor != NULL) { ++many_til_end; src_cursor = src_cursor->link(); } many_til_mid = src_size - many_til_end; // this is how many to advance to replicate cursor position. start(); // put this.cursor at beginning. // DEPENDS ON VALUE OF many_nodes ABOVE for (int i=0; i<many_til_mid; ++i) { advance(); // DEPENDS ON VALUE OF many_nodes ABOVE } /* after the for loop, the new linked_list's cursor should be at the same position as the source's cursor was.*/ } else { cursor = NULL; precursor = NULL; } } template <class Item> linked_list<Item>::~linked_list() { // Destructor list_clear(head_ptr); head_ptr = tail_ptr = cursor = precursor = NULL; many_nodes = 0; } /* MODIFICATION MEMBER FUNCTIONS */ template <class Item> void linked_list<Item>::start() { if (many_nodes > 0) { // if at least one item exists cursor = head_ptr; precursor = NULL; } } template <class Item> void linked_list<Item>::advance() { if (is_item()) { precursor = cursor; cursor = cursor->link(); if ( cursor == NULL ) { precursor = NULL; } } } /* ADDED [ */ template <class Item> typename linked_list<Item>::value_type linked_list<Item>::get(int position) { for (int i=0; i<=position; ++i) { // advance the cursor to the position then return item if (i==0) start(); else advance(); if (i==position) { return current(); } } } template <class Item> void linked_list<Item>::set(int position, const value_type& entry) { if (is_item()) { // only set at a valid position. insert(position, entry); // insert new item to list advance(); remove_current(); // remove old item from list. } } template <class Item> void linked_list<Item>::add(const value_type& entry) { cursor = precursor = NULL; // remove cursor attach_here(entry); // <<-- attaches at end when no cursor. } template <class Item> void linked_list<Item>::remove(int position) { for (int i=0; i<=position; ++i) { // advance the cursor to the position then insert item if (i==0) start(); else advance(); if (i==position) { remove_current(); } } } template <class Item> void linked_list<Item>::insert(int position, const value_type& entry) { for (int i=0; i<=position; ++i) { // advance the cursor to the position then insert item if (i==0) start(); else advance(); if (i==position) { insert_here(entry); } } } /* ] */ template <class Item> void linked_list<Item>::insert_here(const value_type &entry) { /*REMOVED*/ // void linked_list<Item>::insert(const value_type &entry) { /*if the list is empty*/ if (!is_item() && !many_nodes) { cursor = new node<Item>(entry); head_ptr = cursor; tail_ptr = cursor; } /*if the list is not empty and cursor points to the first item*/ else if (is_item() && cursor == head_ptr) { cursor = new node<Item>( entry ); cursor->set_link( head_ptr ); head_ptr = cursor; } /*if the list is not empty and there is no current item*/ else if (!is_item() && many_nodes) { cursor = new node<Item>( entry ); cursor->set_link( head_ptr ); head_ptr = cursor; } /*if the list is not empty and the cursor points somewhere in the middle(including last item)*/ else if (is_item() && cursor != head_ptr) { cursor = new node<Item>( entry ); cursor->set_link( precursor->link() ); precursor->set_link( cursor ); } ++many_nodes; //increase the node count } /*ADDED*/ template <class Item> void linked_list<Item>::attach(int position, const value_type& entry) { for (int i=0; i<=position; ++i) { // advance the cursor to the position then attach item if (i==0) start(); else advance(); if (i==position) { attach_here(entry); } } } template <class Item> void linked_list<Item>::attach_here(const value_type& entry) { /*REMOVED*/ // void linked_list<Item>::attach(const value_type& entry) { /*if the list is empty*/ if (!is_item() && !many_nodes) { cursor = new node<Item>(entry); head_ptr = cursor; tail_ptr = cursor; precursor = NULL; } /*if the list is not empty and cursor points to the first item and there's only one item*/ else if (is_item() && many_nodes == 1) { cursor = new node<Item>( entry ); cursor->set_link( head_ptr->link() ); head_ptr->set_link( cursor ); precursor = head_ptr; tail_ptr = cursor; } /*if the list is not empty and cursor points to the first item and there's more than one item*/ else if (is_item() && many_nodes > 1 && cursor == head_ptr ) { cursor = new node<Item>( entry ); cursor->set_link( head_ptr->link() ); head_ptr->set_link( cursor ); precursor = head_ptr; } /*if the list is not empty and there is no current item*/ else if (!is_item() && many_nodes) { cursor = new node<Item>( entry ); tail_ptr->set_link( cursor ); precursor = tail_ptr; tail_ptr = cursor; } /*if the list is not empty and the cursor points somewhere in the middle(including last item)*/ else if (is_item() && cursor != head_ptr) { if (cursor != tail_ptr) { // if cursor is not at last item cursor = new node<Item>( entry ); } else if (cursor == tail_ptr) { // if cursor is at last item cursor = new node<Item>( entry ); tail_ptr = cursor; } cursor->set_link( (precursor->link())->link() ); (precursor->link())->set_link( cursor ); precursor = precursor->link(); } ++many_nodes; // increase the node count } template <class Item> void linked_list<Item>::remove_current() { if ( is_item() ) { /*If the cursor points to an item in the middle of the list, not tail, not head:*/ if (cursor != head_ptr && cursor != tail_ptr) { precursor->set_link( cursor->link() ); delete cursor; cursor = precursor->link(); } /*If the cursor points to the first item in the list and that is the only item:*/ else if (many_nodes == 1) { delete cursor; cursor = head_ptr = tail_ptr = precursor = NULL; } /*If the cursor points to the first item in the list and there is more than one item:*/ else if ( cursor == head_ptr && many_nodes > 1) { cursor = cursor->link(); delete head_ptr; head_ptr = cursor; } /*If the cursor points to the last item in the list (and there is more than one item)*/ else if ( cursor == tail_ptr && many_nodes > 1) { delete cursor; tail_ptr = precursor; /* #!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!# */ tail_ptr->set_link(NULL); /* #!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!# */ precursor = cursor = NULL; } --many_nodes; } } template <class Item> void linked_list<Item>::operator =(const linked_list& source) { if (this != &source) { list_clear(head_ptr); head_ptr = tail_ptr = cursor = precursor = NULL; many_nodes = 0; int src_size = source.size(); // to replicate cursor position int many_til_end = 0; // to replicate cursor position int many_til_mid = 0; // to replicate cursor position node<Item> *src_cursor = source.cursor; // to replicate cursor position list_copy(source.head_ptr, head_ptr, tail_ptr); /*replicate the size value (before cursor position because functions used for that depend on many_nodes value*/ many_nodes = source.many_nodes; /*replicate the cursor position*/ if (src_cursor != NULL) { while (src_cursor != NULL) { ++many_til_end; src_cursor = src_cursor->link(); } many_til_mid = src_size - many_til_end; // this is how many to advance to replicate cursor position. start(); // put this.cursor at beginning. for (int i=0; i<many_til_mid; ++i) { advance(); } /* after the for loop, the new linked_list's cursor should be at the same position as the source's cursor was.*/ } else { cursor = NULL; precursor = NULL; } } } /* CONSTANT MEMBER FUNCTIONS */ template <class Item> typename linked_list<Item>::value_type linked_list<Item>::current() const { if ( is_item() ) { return cursor->data(); } } }