1
Linked Lists IIDoubly Linked Lists
Chapter 3
2
Objectives
You will be able to: Describe, implement, and use a Doubly
Linked List of integers.
3
Some Issues
Issues in current implementation: Inserting and deleting at either end of the list
requires special case code. Empty list requires special case code.
First node and last node are different from other nodes.
deleteFromTail is inefficient Requires scanning entire list.
Solution: Doubly linked list with node as list head. (Not in book!)
4
Some Other Issues
Issues in current implementation: No way to retrieve a specified node. No way to insert in order. No way to traverse the list.
Solution: Add new methods.
5
Each node has a pointer to the next node and a pointer to the previous node. Section 3.2 in the textbook.
Version in the book still has pointers to the head and tail as members of the list class.
Requires special case code for adding and deleting at the head and the tail.
Doubly Linked List
Figure 3.9
6
Doubly Linked List with List Head Node
We can avoid all special case code by using a Node object as a List Head. Next pointer points to first element of
List. Prev pointer points to last element of
List If List is empty, both point to the List
Head.
7
Doubly Linked List with List Head Node
With a Node as List Head, all nodes in the list are alike. Each node has a Node as next. Each node has a Node as prev. No pointer is ever null.
An empty list is not a special case. There is still a List Head Node, with next and
prev pointers.
The same Insert and Delete code works for all cases!
8
Download
Download example from last class.
http://www.cse.usf.edu/~turnerr/Data_Structures/Downloads/2011_01_12_Singly_Linked_List/
File intSLLst.zip
9
Download example from last class
10
Download example from last class
11
Expand the .zip file
Right click the .zip file icon.
12
Expand the .zip file
13
Select Destination for Expanded File
14
Extraction Complete
15
Downloaded Folder Expanded
Drill down.
16
The Solution Folder
Double click the .sln file to open the solution in Visual Studio
17
Open in Visual Studio
Rebuild solution and test.Be sure we have a known starting point.
18
Program in Action
Now let's modify the list to be a doubly linked list with Listhead Node.
19
Add Class intDLList
20
Add Class intDLList
21
Add Class intDLList
22
Defining Class intDLList
Copy intSLLst.h as initial version of intDLList.h.
Update class names and guard. Add prev pointer to Node class.
23
intDLList.h
#pragma once//************************ intDLList.h ***************// Doubly-linked list class to store integers
class IntDLLNode {public: int info; class IntDLLNode *next; class IntDLLNode *prev;
IntDLLNode(int el, IntDLLNode *ptr1 = 0, IntDLLNode *ptr2 = 0) { info = el; next = ptr1; prev = ptr2; }};
intDLList.hclass IntDLList {public: IntDLList(); ~IntDLList(); int isEmpty() const { return ListHead->next == ListHead; } void addToHead(int); void addToTail(int); int deleteFromHead(); // delete the head and return its info; int deleteFromTail(); // delete the tail and return its info; void deleteNode(int); bool isInList(int) const; void printAll() const;
private: IntDLLNode* ListHead;};
25
main.cpp
Update list class.
Comment out most of body So that we can compile before adding
all methods to IntDLList.cpp
26
main.cpp
#include <iostream>#include "intDLList.h"using namespace std;
int main(){ IntDLList myList;
//myList.addToHead(3); //myList.addToHead(2); //myList.addToHead(1); //myList.addToHead(0);
//cout << "Initial List:\n"; //myList.printAll();
//while (!myList.isEmpty()) //{ ... //} cin.get(); // Hold window open.}
27
Implementing Class intDLList
Start by adding constructor and destructor to intDLList.cpp
Add remaining methods one at a time.
Build after adding each method
28
Constructor
//************************ intDLList.cpp *************#include <iostream>#include "intDLList.h"
using namespace std;
IntDLList::IntDLList(){ ListHead = new IntDLLNode(0); ListHead->next = ListHead; ListHead->prev = ListHead;}
IntDLList::~IntDLList(void){}
Build
29
addToHead
void IntDLList::addToHead(int el) { IntDLLNode *p = new IntDLLNode(el);
p->next = ListHead->next; p->prev = ListHead;
ListHead->next->prev = p; ListHead->next = p;}
Build
30
addToTail
void IntDLList::addToTail(int el) { IntDLLNode *p = new IntDLLNode(el);
p->next = ListHead; p->prev = ListHead->prev;
ListHead->prev->next = p; ListHead->prev = p;}
31
deleteFromHead
int IntDLList::deleteFromHead() { if (isEmpty()) { throw("Attempt to delete from empty list"); } int el = ListHead->next->info;
IntDLLNode *tmp = ListHead->next; ListHead->next->next->prev = ListHead; ListHead->next = ListHead->next->next;
delete tmp; return el;}
32
deleteFromTail
int IntDLList::deleteFromTail() { if (isEmpty()) { throw("Attempt to delete from empty list"); } int el = ListHead->prev->info;
IntDLLNode *tmp = ListHead->prev; tmp->prev->next = ListHead; ListHead->prev = tmp->prev;
delete tmp; return el;}
33
deleteNode
// Delete node with a specified valuevoid IntDLList::deleteNode(int el) { IntDLLNode *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; }
if (p == ListHead) { return; // It's not there. Claim success! }
// p points to node to be deleted. p->prev->next = p->next; p->next->prev = p->prev; delete p;}
34
isInList
bool IntDLList::isInList(int el) const { IntDLLNode *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; }
return p != ListHead;}
35
printAll
void IntDLList::printAll() const { if (isEmpty())
{ cout << "List is empty\n"; return; }
IntDLLNode *p = ListHead->next; while (p != ListHead) { cout << p->info << " "; p = p->next; } cout << endl;}
36
Destructor
Add following the constructor:
IntDLList::~IntDLList(void){ while (!isEmpty()) { deleteFromTail(); } delete ListHead;}
main.cpp#include <iostream>#include "intDLList.h"
using namespace std;
int main(){ IntDLList myList;
myList.addToHead(3); myList.addToHead(2); myList.addToHead(1); myList.addToHead(0);
cout << "Initial List:\n"; myList.printAll();
while (!myList.isEmpty()) { cout << "Deleting head node\n"; myList.deleteFromHead(); cout << "Current List:\n"; myList.printAll(); } cin.get(); // Hold window open.}
38
Program Running
39
Check Error Handling
cout << "\nCalling deleteFromHead for empty list\n"; cout << "This should output an error message\n\n"; try { myList.deleteFromHead(); } catch (const char* err) { cout << err << endl; } cout << "\nTest complete\n";
40
Program Running
41
Test Thoroughly
We need to test the class code much more thoroughly.
Call every method. Set up potential special cases.
Empty List Exactly one node. Multiple nodes
Top Related