943,807 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 2070
  • C++ RSS
You are currently viewing page 1 of this multi-page discussion thread
Sep 2nd, 2009
0

Doubly Linked List Help

Expand Post »
I am working on a doubly linked list assignment for my class and I am getting a segmentation fault on my test for the copy constructor. I don't know if the problem lies within my copyList method or my copy constructor logic. Any assistance be great.

Here is my header file and link to the assignment.
http://turing.cs.niu.edu/~t90kjm1/CS...s01340f09.html

C++ Syntax (Toggle Plain Text)
  1. #ifndef LIST_H
  2. #define LIST_H
  3.  
  4. #include <iostream>
  5.  
  6. template <class T>
  7. class List;
  8.  
  9. template <class T>
  10. std::ostream& operator<<(std::ostream&, const List<T>&);
  11.  
  12. template <class T>
  13. struct LNode
  14. {
  15. T data;
  16. LNode<T>* prev;
  17. LNode<T>* next;
  18.  
  19. LNode(const T&);
  20. };
  21.  
  22. template <class T>
  23. LNode<T>::LNode(const T& newdata)
  24. {
  25. data = newdata;
  26. prev = next = NULL;
  27. }
  28.  
  29. template <class T>
  30. class List
  31. {
  32. friend std::ostream& operator<< <>(std::ostream&, const List<T>&);
  33.  
  34. private:
  35. LNode<T>* head;
  36. LNode<T>* tail;
  37. public:
  38. List();
  39. ~List();
  40. List(const List<T>&);
  41. LNode<T>* copyList(LNode<T>*);
  42. List<T>& operator=(const List<T>&);
  43. void clear();
  44. int size() const;
  45. bool empty() const;
  46. const T& front() const;
  47. T& front();
  48. const T& back() const;
  49. T& back();
  50. void push_front(const T&);
  51. void push_back(const T&);
  52. void pop_front();
  53. void pop_back();
  54. bool operator==(const List<T>&) const;
  55. bool operator<(const List<T>&) const;
  56. };
  57.  
  58. template <class T>
  59. List<T>::List()
  60. {
  61. head = NULL;
  62. tail = NULL;
  63. }
  64.  
  65. template <class T>
  66. List<T>::~List()
  67. {
  68. clear();
  69. }
  70.  
  71. template <class T>
  72. List<T>::List(const List<T>& oldList)
  73. {
  74. head = copyList(oldList.head);
  75. tail = copyList(oldList.tail);
  76. }
  77.  
  78. template <class T>
  79. LNode<T>* List<T>::copyList(LNode<T>* ptr)
  80. {
  81. LNode<T>* newNode;
  82.  
  83. if(ptr==NULL)
  84. return NULL;
  85. else
  86. {
  87. newNode = new LNode<T>(ptr->data);
  88. newNode->prev = copyList(ptr->prev);
  89. newNode->next = copyList(ptr->next);
  90. }
  91. return newNode;
  92. }
  93.  
  94. template <class T>
  95. List<T>& List<T>::operator=(const List<T>& rightOp)
  96. {
  97. if (this != &rightOp)
  98. {
  99. clear();
  100. head = copyList(rightOp.head);
  101. tail = copyList(rightOp.tail);
  102. }
  103. return *this;
  104. }
  105.  
  106. template <class T>
  107. void List<T>::clear()
  108. {
  109. while(!empty())
  110. pop_front();
  111. }
  112.  
  113. template <class T>
  114. int List<T>::size() const
  115. {
  116. LNode<T>* ptr = head;
  117. int count = 0;
  118.  
  119. while(ptr != NULL)
  120. {
  121. count++;
  122. ptr = ptr->next;
  123. }
  124. return count;
  125. }
  126.  
  127. template <class T>
  128. bool List<T>::empty() const
  129. {
  130. if(head == NULL or tail == NULL)
  131. return true;
  132. else
  133. return false;
  134. }
  135.  
  136. template <class T>
  137. const T& List<T>::front() const
  138. {
  139. return head->data;
  140. }
  141.  
  142. template <class T>
  143. T& List<T>::front()
  144. {
  145. return head->data;
  146. }
  147.  
  148. template <class T>
  149. const T& List<T>::back() const
  150. {
  151. return tail->data;
  152. }
  153.  
  154. template <class T>
  155. T& List<T>::back()
  156. {
  157. return tail->data;
  158. }
  159.  
  160. template <class T>
  161. void List<T>::push_front(const T& item)
  162. {
  163. LNode<T>* newNode;
  164.  
  165. if(!empty())
  166. {
  167. newNode->prev = NULL;
  168. newNode->next = head;
  169. head->prev = newNode;
  170. head = newNode;
  171. }
  172. else
  173. {
  174. newNode->prev = NULL;
  175. newNode->next = head;
  176. tail = newNode;
  177. head = newNode;
  178. }
  179. }
  180.  
  181. template <class T>
  182. void List<T>::push_back(const T& item)
  183. {
  184. LNode<T>* newNode;
  185. newNode = new LNode<T>(item);
  186.  
  187. newNode->next = NULL;
  188. newNode->prev = tail;
  189. if(empty())
  190. head = newNode;
  191. else
  192. tail->next = newNode;
  193. tail = newNode;
  194. }
  195.  
  196. template <class T>
  197. void List<T>::pop_front()
  198. {
  199. if(size() > 1)
  200. {
  201. LNode<T>* delNode = head;
  202. head = delNode->next;
  203. head->prev = NULL;
  204. delete delNode;
  205. }
  206. if(size() == 1)
  207. {
  208. LNode<T>* delNode = head;
  209. head = delNode->next;
  210. tail = NULL;
  211. delete delNode;
  212. }
  213. }
  214.  
  215. template <class T>
  216. void List<T>::pop_back()
  217. {
  218. if(size() > 1)
  219. {
  220. LNode<T>* delNode = tail;
  221. tail = delNode->prev;
  222. tail->next = NULL;
  223. delete delNode;
  224. }
  225. if(size() == 1)
  226. {
  227. LNode<T>* delNode = tail;
  228. tail = delNode->prev;
  229. head = NULL;
  230. delete delNode;
  231. }
  232. }
  233.  
  234. template <class T>
  235. bool List<T>::operator==(const List<T>& rightOp) const
  236. {
  237. LNode<T>* p1;
  238. LNode<T>* p2;
  239.  
  240. while(p1 != NULL and p2 != NULL)
  241. {
  242. if(p1->data != p2->data)
  243. return false;
  244. }
  245. if(p1 == NULL and p2 == NULL)
  246. return true;
  247. else
  248. return false;
  249. }
  250.  
  251. template <class T>
  252. bool List<T>::operator<(const List<T>& rightOp) const
  253. {
  254. LNode<T>* p1;
  255. LNode<T>* p2;
  256.  
  257. while(p1 != NULL and p2 != NULL)
  258. {
  259. if(p1->data < p2->data)
  260. return true;
  261. if(p1->data > p2->data)
  262. return false;
  263. }
  264. if(p2 == NULL)
  265. return false;
  266. else
  267. return true;
  268. }
  269.  
  270. template <class T>
  271. std::ostream& operator<<(std::ostream& leftOp, const List<T>& rightOp)
  272. {
  273. LNode<T>* current;
  274.  
  275. for (current=rightOp.head; current != NULL; current = current->next)
  276. std::cout << current->data << " ";
  277. return leftOp;
  278. }
  279. #endif /*LIST_H*/
Similar Threads
Reputation Points: 10
Solved Threads: 0
Junior Poster
lancevo3 is offline Offline
146 posts
since Feb 2009
Sep 2nd, 2009
0

Re: Doubly Linked List Help

I dont understand why you use copyList method for just copying two pointers...
For copying one list to another you must copy head and tail pointers.
So your copy constructror will be like this
cpp Syntax (Toggle Plain Text)
  1. template <class T>
  2. List<T>::List(const List<T>& oldList)
  3. {
  4. this->head = oldList.head;
  5. this->tail = oldList.tail;
  6. }
And another one - c++ does not have "and" operator. Just use "&&" operator

P.S. I advise to clean "copyList" method. He can be replaced assignment of head and tail pointers.
Last edited by Protuberance; Sep 2nd, 2009 at 4:37 pm.
Reputation Points: 78
Solved Threads: 17
Junior Poster in Training
Protuberance is offline Offline
88 posts
since Aug 2009
Sep 2nd, 2009
0

Re: Doubly Linked List Help

I went ahead and updated my copy consturctor as you said and that worked great, thank you!

On this part of my output I am getting an error:


Testing clear() of non-empty list...
list 1 (size 0):
list 2 (size 4): 0 32178176 32178208 32178240

The error is with the list 2.

This is the code from the driver for that line.

C++ Syntax (Toggle Plain Text)
  1. cout << "list 2 (size " << list2.size() << "): " << list2 << endl << endl;
Reputation Points: 10
Solved Threads: 0
Junior Poster
lancevo3 is offline Offline
146 posts
since Feb 2009
Sep 2nd, 2009
0

Re: Doubly Linked List Help

I recommend you think twice about simple copying of head and tail pointers to copy one list to another. This is called shallow copy and works okay in simple programs but it can quickly cause problems if you aren't aware of what is happening. In particular, under this scenario if either list is deleted then the other list is useless because there is now no longer any place in memory to point to.

I recommend doing hard copy within the copy constructor, copy function. That way each list has it's own memory, even if it contains the same information.

Don't try to copy an empty list. If the list to copy is empty, then return from the function/constructor.
Reputation Points: 718
Solved Threads: 373
Nearly a Posting Maven
Lerner is offline Offline
2,253 posts
since Jul 2005
Sep 2nd, 2009
0

Re: Doubly Linked List Help

If your operator=() works, extract the code that creates a new list with the one provided as a parameter and use it in your copy constructor. Search for the refactoring tip Extract Method.
Last edited by GDICommander; Sep 2nd, 2009 at 7:48 pm.
Reputation Points: 72
Solved Threads: 26
Posting Whiz in Training
GDICommander is offline Offline
209 posts
since Jun 2008
Sep 2nd, 2009
0

Re: Doubly Linked List Help

I tried the copy constructor posted and its giving me a program crash this just doesn't look right to me either any ideas whats up with it?

C++ Syntax (Toggle Plain Text)
  1. template <class T>
  2. List<T>::List(const List<T>& oldList)
  3. {
  4. this->head = oldList.head;
  5. this->tail = oldList.tail;
  6. }
Reputation Points: 10
Solved Threads: 0
Junior Poster
lancevo3 is offline Offline
146 posts
since Feb 2009
Sep 3rd, 2009
0

Re: Doubly Linked List Help

Click to Expand / Collapse  Quote originally posted by lancevo3 ...
I tried the copy constructor posted and its giving me a program crash this just doesn't look right to me either any ideas whats up with it?

C++ Syntax (Toggle Plain Text)
  1. template <class T>
  2. List<T>::List(const List<T>& oldList)
  3. {
  4. this->head = oldList.head;
  5. this->tail = oldList.tail;
  6. }
What kind of error did you get?
AV(Access Violation)
Exception
Segmentation fault
?

If you don't try to copy an empty list, that code works correctly.
For empty list just place condition before assignment
cpp Syntax (Toggle Plain Text)
  1. template <class T>
  2. List<T>::List(const List<T>& oldList)
  3. {
  4. if(!oldList.isEmpty())
  5. {
  6. this->head = oldList.head;
  7. this->tail = oldList.tail;
  8. }
  9. else
  10. throw "Empty list";
  11. }
  12.  
  13. //isEmpty method
  14. template <class T>
  15. bool List<T>::isEmpty() const
  16. {
  17. return head == NULL;
  18. }

Or if you wanna copy list, then delete it, then use copy method. Like that
cpp Syntax (Toggle Plain Text)
  1. template <class T>
  2. void List<T>::copyList(const List<T> &source)
  3. {
  4. //condition for empty list
  5. LNode<T> *source_head_temp = source.head;
  6. while(source_head_temp)
  7. {
  8. push_back(source_head_temp->data);
  9. source_head_temp = source_head_temp->next;
  10. }
  11. }
I hope it helps you.
Reputation Points: 78
Solved Threads: 17
Junior Poster in Training
Protuberance is offline Offline
88 posts
since Aug 2009
Sep 3rd, 2009
0

Re: Doubly Linked List Help

Mock up copy constructor. Code untested. I'm comfortable with the logic and the comments. Adjustable to your needs as desired.
C++ Syntax (Toggle Plain Text)
  1. //use deep copy protocol to copy rhs into a new List using a copy constructor.
  2. //type Node is used to create type List.
  3. //List is doubly linked
  4. //List always adds to the end
  5. List(const List & rhs)
  6. {
  7. if(rhs.count == 0) //rhs is empty, so assign default values to new List member variables
  8. {
  9. count = 0;
  10. firstNode = NULL;
  11. lastNode = NULL;
  12. }
  13. else
  14. {
  15. //declare a Node to run rhs, start with first node in rhs.
  16. Node * current = rhs.firstNode;
  17.  
  18. //assign default values to member variables of new List
  19. count = 0;
  20. firstNode = lastNode = NULL;
  21.  
  22. //use a loop to copy data from rhs into new List one Node at a time
  23. while(current != NULL)
  24. {
  25. //create a new Node to enter into the new List
  26. Node newNode = new Node;
  27. newNode->prev = NULL;
  28. newNode->next = NULL;
  29. newNode->data = current->data;
  30.  
  31. //add new Node to new List
  32. if(count == 0) //new list is empty
  33. firstNode = lastNode = newNode;
  34. else //add new Node to end of new List
  35. {
  36. lastNode->next = newNode;
  37. newNode->prev = lastNode;
  38. lastNode = lastNode->next;
  39. }
  40.  
  41. //increment count and get next node in rhs to copy into new List
  42. ++count;
  43. current = current->next;
  44. }
  45. }
  46. }
Reputation Points: 718
Solved Threads: 373
Nearly a Posting Maven
Lerner is offline Offline
2,253 posts
since Jul 2005
Sep 5th, 2009
0

Re: Doubly Linked List Help

I been able to get this list going for the most part but I am getting a segmentation fault and I believe its being caused by my equality operator, I though I had everything coded right. Any thoughts?

C++ Syntax (Toggle Plain Text)
  1. template <class T>
  2. bool List<T>::operator==(const List<T>& rightOp) const
  3. {
  4. LNode<T>* p1;
  5. LNode<T>* p2;
  6.  
  7. while(p1 != NULL and p2 != NULL)
  8. {
  9. if(p1->data != p2->data)
  10. return false;
  11. }
  12. if(p1 == NULL and p2 == NULL)
  13. return true;
  14. else
  15. return false;
  16. }
Reputation Points: 10
Solved Threads: 0
Junior Poster
lancevo3 is offline Offline
146 posts
since Feb 2009
Sep 5th, 2009
0

Re: Doubly Linked List Help

firstly,

logical and in C++ is represented by '&&' so you will need to have.

C++ Syntax (Toggle Plain Text)
  1. while(p1 != NULL and p2 != NULL)

Changed to


C++ Syntax (Toggle Plain Text)
  1. while(p1 != NULL && p2 != NULL)

The same applies to the if loop below as well.


Secondly, Your Logical error is that you make 2 nodes p1 and p2, but donot assign any location for them to point to.

So it goes on looping infinitely i guess.

you should instead do something like this.

C++ Syntax (Toggle Plain Text)
  1. p1= this-> head;
  2. p2= rightOp.head;
Then let it go through the while loop and. During the while loop checks you will need to move to the next position to.

so

C++ Syntax (Toggle Plain Text)
  1. while(p1 != NULL and p2 != NULL)
  2. {
  3. if(p1->data != p2->data)
  4. return false;
  5.  
  6. p1= p1->next;
  7. p2= p2->next;
  8. }
  9. return true;
Last edited by Sky Diploma; Sep 5th, 2009 at 3:49 am. Reason: Code corrections
Reputation Points: 673
Solved Threads: 125
Practically a Posting Shark
Sky Diploma is offline Offline
818 posts
since Mar 2008

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: link list
Next Thread in C++ Forum Timeline: Problem Setting up Variables for Program





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC