Escolar Documentos
Profissional Documentos
Cultura Documentos
Slides This chapter presents a sample implementation of a linked list, encapsulated in a C++
class.
1. Table of Contents
2. Linked List Example The primary goals of this implementation are:
• to provide a proper separation of functionality.
3. Node Class
• to design the list to serve as a container; i.e., the list should be able to store
4. Node Class Constructors data elements of any type.
5. Node Class Mutators
6. Node Class Reporters First, a LinkNode class is used to encapsulate the low-level pointer operations.
7. Linked List Class
8. LinkList Constructor Second, a LinkList class is used to encapsulate a list of LinkNode objects.
9. LinkList Destructor
10. LinkList Reporters Third, an Item class is used to encapsulate the data and separate it from the pointers
11. LinkList PrefixMutator that define the list structure.
12. LinkList Insert Mutator
13. LinkList Position Mutators The basic view is that each list node provides a data “socket” that is capable of
accepting any type of data element:
14. LinkList Delete Curr Mutator
15. LinkList Delete Value Mutator
16. LinkList Set Curr Mutators Data
17. LinkList Reporter Element
Data Element Class
Next
18.
19. Data Element Class Equality Operator “Data Socket”
20. LinkList Search
21. Alternate Implementation
22. Merge Lists (preservation)
23. Ordered Insertion
Warning: the LinkList class given in this chapter is intended for
24. Merge Lists (no preservation) in situ instructional purposes. The given implementation contains a
25. Merge Lists in situ (cont) number of known flaws, and perhaps some unknown flaws as
well. Caveat emptor.
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
The LinkNode class neither knows nor cares what an Item variable
is — a LinkNode is a container. We are assuming that Item is a class. (Do you see where?)
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
class LinkList {
private: The object definition:
LinkNode* Head; // points to head node in list
LinkNode* Tail; // points to tail node in list LinkList TheList;
LinkNode* Curr; // points to "current" node
public:
LinkList(); //constructor One
Oneline
lineFns
Fnscould
couldbe
be
Results in the following state:
~LinkList();//destructor “inline” for efficiency.
bool isEmpty() const; “inline” for efficiency. TheList
bool inList() const;
bool PrefixNode(const Item& newData); Head Curr Tail
bool Insert(const Item& newData);
bool Advance();
void gotoHead();
• • •
void gotoTail(); consts
constsfor
forprotection
protection
bool DeleteCurrentNode();
bool DeleteValue(const Item& Target);
Item getCurrentData() const;
void setCurrentData(const Item& newData);
// missing: copy constructor, assignment overload FNs
};
#endif See Copying Objects notes for missing functions.
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Code Code
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Default destructor for LinkList objects. // Indicates whether LinkList is empty.
// //
// Parameters: none // Parameters: none
// Pre: LinkList object has been constructed // Pre: LinkList object has been constructed
// Post: LinkList object has been destructed; // Post: returns true if object contains an
// all dynamically-allocated nodes // empty list, and false otherwise
// have been deallocated. //
// bool LinkList::isEmpty() const {
LinkList::~LinkList() {
return (Head == NULL);
LinkNode* toKill = Head; }
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Code: inserting at the head of the list Code: inserting after the current position
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Inserts a new LinkNode at the front of the // Inserts a new LinkNode immediately after the
// list. // current position in the list.
// //
// Parameters: // Parameters:
// newData Data element to be inserted // newData Data element to be inserted
// Pre: LinkList object has been constructed // Pre: LinkList object has been constructed
// Post: LinkNode containing newData has been // Post: LinkNode containing newData has been
// constructed and inserted at the // constructed and inserted after
// beginning of the list, if // the current position, if possible.
// possible. //
// // Returns: true if operation succeeds
// Returns: true if operation succeeds // false otherwise
// false otherwise //
// bool LinkList::Insert(const Item& newData) {
bool LinkList::PrefixNode(const Item& newData) {
if (Curr == NULL) return false;
LinkNode* newNode = new(nothrow) LinkNode(newData);
LinkNode* newNode = new(nothrow) LinkNode(newData);
if (newNode == NULL) return false;
if (newNode == NULL) return false;
if ( isEmpty() ) { Pointer
Pointerdereference.
dereference.
newNode->setNext(NULL); This
Thisisisaavery
verygood
goodplace
place if ( isEmpty() ) Why should this
Head = Tail = Curr = newNode; to return false;
return true; toblow
blowup upatatruntime
runtimeifif case never occur?
you
youdon’t
don’tverify
verifynewNode
newNode
} isisnot newNode->setNext(Curr->getNext());
notNULL
NULLprior
priorto
tothis
this Curr->setNext(newNode);
newNode->setNext(Head); statement.
statement. if (Curr == Tail)
Head = newNode; Tail = newNode;
IsIsthis
thisstatement
statement
return true; necessary? return true;
} necessary?(Included
(Includedas
as }
aaprecaution?)
precaution?) Note
Notetest
testfor
forvalid
valid
current
currentposition.
position.
Uses
UsesLinkNode
LinkNodemember
memberfunctions
functionsto
tomodify
modify
node
nodepointers
pointers——thisthisgives
givesaaseparation
separationbetween
between
the
the“high”
“high”level
levellist
listfunctions
functionsthe
theuser
usersees
seesand
and
the
the“massaging”
“massaging”of ofthe
thepointers.
pointers.
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Code: changing the current position Code: deleting the current node
/////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
// Resets the current position to the head of the list. // Deletes the node at the current position, if possible.
// //
void LinkList::gotoHead() { // Returns: true if operation succeeds false otherwise
//
Curr = Head; bool LinkList::DeleteCurrentNode() {
}
LinkNode* delThis;
/////////////////////////////////////////////////////// Test
Testfor
forvalid
validcurrent
current
// Resets the current position to the tail of the list. if (Curr == NULL) return false; position.
position.
//
void LinkList::gotoTail() { if (Curr == Head) { //delete Head node
delThis = Curr; Handle
Curr = Tail; Head = Head->getNext(); Handledeletion
deletionof
of
} Curr = Head; head
headnode.
node.
if (Tail == delThis) Tail = Curr;
////////////////////////////////////////////////// delThis->setNext(NULL);
// Advances the current position to the next node delete delThis;
// in the list, if there is one; leaves the return true;
// current position unchanged otherwise. }
//
// Parameters: none //locate Curr's previous node
// Pre: LinkList object has been constructed LinkNode* prevNode = Head; Find
// Post: Current position advanced to the while (prevNode != NULL && Findprevious
previousnode.
node.
// next node, if possible. prevNode->getNext() != Curr)
// prevNode = prevNode->getNext();
// Returns: true if operation succeeds
// false otherwise //check for valid Curr pointer IfIfnot
notfound,
found,error.
error.
// if (prevNode == NULL) return false;
bool LinkList::Advance() {
Note //previous found bypass and delete Curr
if (Curr != NULL) { Notetest
testfor
forvalid
valid delThis = Curr; Handle
Curr = Curr->getNext(); current
currentposition.
position. Handledeletion
prevNode->setNext(Curr->getNext()); node deletionof
of
return true; Curr->setNext(NULL); nodeininmiddle
middleor
oratat
} Curr = prevNode->getNext(); tail of list.
tail of list.
else if (Tail == delThis) Tail = prevNode;
return false; delete delThis;
} return true;
}
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
LinkList Delete Value Mutator 7. LL Class 15 LinkList Set Curr Mutators 7. LL Class 16
Code: deleting a list value Code: changing the Data in the current node
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Deletes the (first) node in the list that // Replaces the Data element of the current node,
// contains the specified Data element. // if possible; assert() failure will kill program
// // if not, so test with inList() before calling.
// Parameters: //
// Target Data value to be deleted // Parameters:
// Pre: LinkList object has been constructed // newData Data element used for updating
// Equality oper. overloaded for Item // Pre: LinkList object has been constructed
// Post: First node in the list that contains // Post: Data element of current node has
// the specified data value has // been updated, if possible.
// been deleted. //
// void LinkList:: setCurrentData(const Item& newData) {
// Returns: true if operation succeeds
// false otherwise assert (Curr != NULL);
//
bool LinkList::DeleteValue(const Item& Target) { Curr->setData(newData); IfIfno
nocurrent
current
} position,
position,die.
die.
LinkNode* myCurr = Head;
LinkNode* myTrailer = NULL; Look
Lookfor
formatching
matchingnode.
node.
while ( (myCurr != NULL) &&
!(myCurr->getData() == Target) ) { This implementation places a burden on the user of the class. If
myTrailer = myCurr;
myCurr = myCurr->getNext(); the current position is undefined (e.g., if the list is empty), then the
} IfIfnot
notfound,
found,error.
error.
call to assert() will cause the program to terminate rather
if (myCurr == NULL) return false;
gracelessly. A better design would alert the user/client:
if (myTrailer == NULL) Handle
Handlecase
casetarget
targetisis
Head = Head->getNext(); the
thehead
headnode.
node.
else bool LinkList:: setCurrentData(const ItemType& newData)
myTrailer->setNext(myCurr->getNext()); {
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Code: returning the Data in the current node The user must typedef Item to match the data class that he/she
really wishes to use. Recall the Inventory Class:
//////////////////////////////////////////////////
// Returns the Data element of the current node,
// if possible; assert() failure will kill program // *********** INVENTORY CLASS DECLARATION ************
// if not, so test with inList() before calling.
// class InvItem {
// Parameters: none private:
// Pre: LinkList object has been constructed string SKU; //StocK Unit #: KEY FIELD
// Post: Data element of current node has string Description; //Item Details
// been returned, if possible. int Retail; //Selling Price
// int Cost; //Store Purchase Price
Item LinkList::getCurrentData() const {
int Floor; //Number of Items on display
IfIfno int Warehouse; //Number of Items in stock
assert (Curr != NULL); nocurrent
current
position,
position,die.
die.
return (Curr->getData()); public:
} InvItem(); //default constructor
InvItem(const string& iSKU, //parameter constructor
const string& iDescription,
This possible premature termination due to an undefined current int iRetail,
position could be eliminated by having the function return a int iCost,
int iFloor,
pointer to a copy of the data element, or by having the function use int iWarehouse);
a reference parameter to communicate a copy of the data value to
//Reporter Member Functions
the caller, and also return true/false to indicate success. // . . . Unchanged from previous declaration
//Mutator Member Functions
Better design: maintain an internal error state in the class. (E.g., // . . . Unchanged from previous declaration
similar to the stream status in <iostream>). //Operator Overloads
bool operator==(const InvItem& anItem);
Note: a pointer to an object in a list (i.e. Item*) or a reference to }; // class InvItem
an object in a list (i.e. Item&) should NOT be returned by a
member function. Why? typedef InvItem Item; Required type name
equivalency definition
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
By only testing the SKU members for equality the code is Note: this function is “external” to the LinkList class. The inclusion of
reflecting a design decision that the SKU numbers of all Inventory the function as a LinkList class member function is left as an exercise.
items must be unique.
//OK? Why is the second condition in the while boolean expression not stated:
return (SKU == anItem.SKU); (anItem != (List.getCurrentData())
Even more subtle, why can it not also be stated:
!(anItem == (List.getCurrentData()))
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
// Insert the Item in the ascending ordered LinkList void LinkList::Mergelists(LinkList& L2) {
bool insertion(LinkList& list, const Item & newData){ LinkNode* MergeHead; Assumes
LinkNode* trail1; Assumeselements
elements
list.gotoHead(); LinkNode* trail2; within
withinlist
listare
areunique.
unique.
Item i1, i2;
while ( (list.inList()) &&
(list.getCurrentData() < newData ) ) if (Head == NULL) { //this empty return L2 List
list.Advance(); Head = L2.Head; L2.Head = NULL;
Curr = L2.Curr; L2.Curr = NULL;
if (list.isEmpty()) Tail = L2.Tail; L2.Tail = NULL;
return(list.PrefixNode(newData)); return;
else if (!list.inList()) { //newData > tail }//if
list.gotoTail(); //append to tail if (L2.Head == NULL) //return this List
return(list.Insert(newData)); return;
}
else { //insert before Current list element // set merge list head to smaller first item
Item tmpData = list.getCurrentData(); MergeHead = (Head->getData() < L2.Head->getData())
list.setCurrentData(newData); ? Head : L2.Head;
return(list.Insert(tmpData));
} while ( (Head != NULL) && (L2.Head != NULL) ) {
} i1 = Head->getData();
Sets
Setscurrent
currentnode
nodetoto i2 = L2.Head->getData();
contain
containnewData
newDataitem
item
and
and inserts old nodedata
inserts old node data if ( i1 == i2 ){//egual current merge items
item trail2 = L2.Head->getNext();//advance L2.Head
itemafter
aftercurrent
currentnode.
node. L2.Head->setNext(Head); //due to initial/curr
L2.Head = trail2; //equal elements
}//if
while
whileconditions
conditionsrely
relyupon
upon
Boolean
Booleanshort-circuiting.
short-circuiting.
Problem:
Problem:ififList2
List2contains
contains
multiple
multipleitems
itemsequal
equalto
to
WARNING:
WARNING:untested
untestedcode!
code! WARNING:
WARNING:untested
untestedcode!
code! head of list1?
head of list1?
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD
else
if ( i1 < i2 ) { //advance this list
while ( (Head != NULL) && //until end of list
(Head->getData() < i2) ) { //or smaller
trail1 = Head; // item is found
Head = Head->getNext();
} //while
trail1->setNext(L2.Head);
} //if
else { //i2 < i1 //advance L2 list
while ( (L2.Head != NULL) &&//until end list
(L2.Head->getData() < i1) ) { //or
trail2 = L2.Head; //smaller item is
L2.Head = L2.Head->getNext(); //found
} //while
trail2->setNext(Head);
} //else
} //while
WARNING:
WARNING:untested
untestedcode!
code!
Computer Science Dept Va Tech Aug., 2001 Intro Data Structures & SE ©1995-2001 Barnette ND, McQuain WD