adding ds list code

This commit is contained in:
Jidong Xiao
2023-10-09 10:58:45 -04:00
parent 8bcb951cee
commit 669ace5797
2 changed files with 269 additions and 1 deletions

View File

@@ -3,7 +3,7 @@
## Checkpoint 1 ## Checkpoint 1
*estimate: 20-30 minutes* *estimate: 20-30 minutes*
The implementation of the dslist class is incomplete. In particular, the class is missing the destroy_list The implementation of the dslist class in [dslist.h](dslist.h) is incomplete. In particular, the class is missing the destroy_list
private member function that is used by the destructor and the clear member function. The provided test private member function that is used by the destructor and the clear member function. The provided test
case in [checkpoint1.cpp](checkpoint1.cpp) works “fine”, so whats the problem? case in [checkpoint1.cpp](checkpoint1.cpp) works “fine”, so whats the problem?

View File

@@ -0,0 +1,268 @@
#ifndef dslist_h_
#define dslist_h_
// A simplified implementation of the STL list container class,
// including the iterator, but not the const_iterators. Three
// separate classes are defined: a Node class, an iterator class, and
// the actual list class. The underlying list is doubly-linked, but
// there is no dummy head node and the list is not circular.
#include <cassert>
// -----------------------------------------------------------------
// NODE CLASS
template <class T>
class Node {
public:
Node() : next_(NULL), prev_(NULL) {}
Node(const T& v) : value_(v), next_(NULL), prev_(NULL) {}
// REPRESENTATION
T value_;
Node<T>* next_;
Node<T>* prev_;
};
// A "forward declaration" of this class is needed
template <class T> class dslist;
// -----------------------------------------------------------------
// LIST ITERATOR
template <class T>
class list_iterator {
public:
// default constructor, copy constructor, assignment operator, & destructor
list_iterator(Node<T>* p=NULL) : ptr_(p) {}
// NOTE: the implicit compiler definitions of the copy constructor,
// assignment operator, and destructor are correct for this class
// dereferencing operator gives access to the value at the pointer
T& operator*() { return ptr_->value_; }
// increment & decrement operators
list_iterator<T>& operator++() { // pre-increment, e.g., ++iter
ptr_ = ptr_->next_;
return *this;
}
list_iterator<T> operator++(int) { // post-increment, e.g., iter++
list_iterator<T> temp(*this);
ptr_ = ptr_->next_;
return temp;
}
list_iterator<T>& operator--() { // pre-decrement, e.g., --iter
ptr_ = ptr_->prev_;
return *this;
}
list_iterator<T> operator--(int) { // post-decrement, e.g., iter--
list_iterator<T> temp(*this);
ptr_ = ptr_->prev_;
return temp;
}
// the dslist class needs access to the private ptr_ member variable
friend class dslist<T>;
// Comparions operators are straightforward
bool operator==(const list_iterator<T>& r) const {
return ptr_ == r.ptr_; }
bool operator!=(const list_iterator<T>& r) const {
return ptr_ != r.ptr_; }
private:
// REPRESENTATION
Node<T>* ptr_; // ptr to node in the list
};
// -----------------------------------------------------------------
// LIST CLASS DECLARATION
// Note that it explicitly maintains the size of the list.
template <class T>
class dslist {
public:
// default constructor, copy constructor, assignment operator, & destructor
dslist() : head_(NULL), tail_(NULL), size_(0) {}
dslist(const dslist<T>& old) { copy_list(old); }
dslist& operator= (const dslist<T>& old);
~dslist() { destroy_list(); }
typedef list_iterator<T> iterator;
// simple accessors & modifiers
unsigned int size() const { return size_; }
bool empty() const { return head_ == NULL; }
void clear() { destroy_list(); }
// read/write access to contents
const T& front() const { return head_->value_; }
T& front() { return head_->value_; }
const T& back() const { return tail_->value_; }
T& back() { return tail_->value_; }
// modify the linked list structure
void push_front(const T& v);
void pop_front();
void push_back(const T& v);
void pop_back();
iterator erase(iterator itr);
iterator insert(iterator itr, const T& v);
iterator begin() { return iterator(head_); }
iterator end() { return iterator(NULL); }
private:
// private helper functions
void copy_list(const dslist<T>& old);
void destroy_list();
//REPRESENTATION
Node<T>* head_;
Node<T>* tail_;
unsigned int size_;
};
// -----------------------------------------------------------------
// LIST CLASS IMPLEMENTATION
template <class T>
dslist<T>& dslist<T>::operator= (const dslist<T>& old) {
// check for self-assignment
if (&old != this) {
destroy_list();
copy_list(old);
}
return *this;
}
template <class T>
void dslist<T>::push_front(const T& v) {
}
template <class T>
void dslist<T>::pop_front() {
}
template <class T>
void dslist<T>::push_back(const T& v) {
Node<T>* newp = new Node<T>(v);
// special case: initially empty list
if (!tail_) {
head_ = tail_ = newp;
} else {
// normal case: at least one node already
newp->prev_ = tail_;
tail_->next_ = newp;
tail_ = newp;
}
++size_;
}
template <class T>
void dslist<T>::pop_back() {
}
// do these lists look the same (length & contents)?
template <class T>
bool operator== (dslist<T>& left, dslist<T>& right) {
if (left.size() != right.size()) return false;
typename dslist<T>::iterator left_itr = left.begin();
typename dslist<T>::iterator right_itr = right.begin();
// walk over both lists, looking for a mismatched value
while (left_itr != left.end()) {
if (*left_itr != *right_itr) return false;
left_itr++; right_itr++;
}
return true;
}
template <class T>
bool operator!= (dslist<T>& left, dslist<T>& right){ return !(left==right); }
template <class T>
typename dslist<T>::iterator dslist<T>::erase(iterator itr) {
assert (size_ > 0);
--size_;
iterator result(itr.ptr_->next_);
// One node left in the list.
if (itr.ptr_ == head_ && head_ == tail_) {
head_ = tail_ = 0;
}
// Removing the head in a list with at least two nodes
else if (itr.ptr_ == head_) {
head_ = head_->next_;
head_->prev_ = 0;
}
// Removing the tail in a list with at least two nodes
else if (itr.ptr_ == tail_) {
tail_ = tail_->prev_;
tail_->next_ = 0;
}
// Normal remove
else {
itr.ptr_->prev_->next_ = itr.ptr_->next_;
itr.ptr_->next_->prev_ = itr.ptr_->prev_;
}
delete itr.ptr_;
return result;
}
template <class T>
typename dslist<T>::iterator dslist<T>::insert(iterator itr, const T& v) {
++size_ ;
Node<T>* p = new Node<T>(v);
p->prev_ = itr.ptr_->prev_;
p->next_ = itr.ptr_;
itr.ptr_->prev_ = p;
if (itr.ptr_ == head_)
head_ = p;
else
p->prev_->next_ = p;
return iterator(p);
}
template <class T>
void dslist<T>::copy_list(const dslist<T>& old) {
size_ = old.size_;
// Handle the special case of an empty list.
if (size_ == 0) {
head_ = tail_ = 0;
return;
}
// Create a new head node.
head_ = new Node<T>(old.head_->value_);
// tail_ will point to the last node created and therefore will move
// down the new list as it is built
tail_ = head_;
// old_p will point to the next node to be copied in the old list
Node<T>* old_p = old.head_->next_;
// copy the remainder of the old list, one node at a time
while (old_p) {
tail_->next_ = new Node<T>(old_p->value_);
tail_->next_->prev_ = tail_;
tail_ = tail_->next_;
old_p = old_p->next_;
}
}
template <class T>
void dslist<T>::destroy_list() {
}
#endif