Linked Lists

Download Report

Transcript Linked Lists

Linked Lists
Chapter 4
Basic Linked List Node
struct Node
{
char m_item;
Node * m_next;
};
typedef Node * ptrType;
//or
struct Node; //forward declaration
typedef Node * PtrType;
typedef char ItemType;
struct Node
{
ItemType m_item;
PtrType m_next;
};
7/17/2015
CSCD 326
2
Pointer to the Head of a List
• For any given linked list, you need something
that will ALWAYS point at the beginning of the
list.
• To accomplish this you need a pointer to a
node.
• Some implementations of linked lists involve
a “dummy node” that the head of the list
always points at. This simplifies some
operations where you have to watch out for
and empty list (insert and delete operations).
7/17/2015
CSCD 326
3
LinkedList.h
//***********************************************
// Header file LinkedList.h for the ADT list.
// Pointer-based implementation.
//***********************************************
#include <stddef.h>
// for NULL
#include <assert.h>
// for assert()
struct listNode;
// linked list node
typedef listNode* ptrType; // pointer to node
typedef char listItemType; //could be any type!
struct listNode
{ listItemType Item;
ptrType
Next;
}; // end struct
7/17/2015
// a node on the list
// a data item on the list
// pointer to next node
CSCD 326
4
LinkedList.h continued
class listClass
{
public:
// constructors and destructor:
listClass();
//default constructor
listClass(const listClass& L); // copy constructor
~listClass();
// destructor
// list operations:
bool ListIsEmpty() const;
int ListLength() const;
void ListInsert(int NewPosition, listItemType
NewItem,bool& Success);
void ListDelete(int Position, bool& Success);
void ListRetrieve(int Position, listItemType&
DataItem, bool& Success) const;
7/17/2015
CSCD 326
5
LinkedList.h continued
private:
int
Size;
ptrType Head;
// number of items in list
// pointer to linked list of items
ptrType PtrTo(int Position) const;
// Returns a pointer to the Position-th node
// in the linked list.
}; // end class
// End of header file.
7/17/2015
CSCD 326
6
LinkedList.cpp
//***********************************************
//Implementation file ListP.cpp for the ADT list.
// Pointer-based implementation.
//***********************************************
#include "ListP.h"
// header file
listClass::listClass(): Size(0), Head(NULL)
{
} // end default constructor
7/17/2015
CSCD 326
7
LinkedList.cpp continued
listClass::listClass(const listClass& L):
Size(L.Size)
{
if (L.Head == NULL)
Head = NULL; // original list is empty
else
{ // copy first node
Head = new listNode;
assert(Head != NULL); // check allocation
Head->Item = L.Head->Item;
// copy rest of list
ptrType NewPtr = Head; // new list pointer
// NewPtr points to last node in new list
// OrigPtr points to nodes in original list
7/17/2015
CSCD 326
8
LinkedList.cpp continued
for (ptrType OrigPtr = L.Head->Next;
OrigPtr != NULL;
OrigPtr = OrigPtr->Next)
{ NewPtr->Next = new listNode;
assert(NewPtr->Next != NULL);
NewPtr = NewPtr->Next;
NewPtr->Item = OrigPtr->Item;
} // end for
}
NewPtr->Next = NULL;
} // end if
// end copy constructor
7/17/2015
CSCD 326
9
LinkedList.cpp continued
listClass::~listClass()
{
bool Success;
while (!ListIsEmpty())
ListDelete(1, Success);
} // end destructor
bool listClass::ListIsEmpty() const
{
return bool(Size == 0);
} // end ListIsEmpty
int listClass::ListLength() const
{
return Size;
} // end ListLength
7/17/2015
CSCD 326
10
LinkedList.cpp continued
ptrType listClass::PtrTo(int Position) const
// -------------------------------------------------// Locates a specified node in a linked list.
// Precondition: Position is the number of the
// desired node.
// Postcondition: Returns a pointer to the desired
// node. If Position < 1 or Position > the number of
// nodes in the list, returns NULL.
// -------------------------------------------------{
if ( (Position < 1) || (Position > ListLength()) )
return NULL;
else // count from the beginning of the list
{ ptrType Cur = Head;
for (int Skip = 1; Skip < Position; ++Skip)
Cur = Cur->Next;
return Cur;
} // end if
} // end PtrTo
7/17/2015
CSCD 326
11
LinkedList.cpp continued
void listClass::ListRetrieve(int Position,
listItemType& DataItem,bool& Success) const
{
Success = bool( (Position >= 1) &&
(Position <= ListLength()) );
if (Success)
{ // get pointer to node, then data in node
ptrType Cur = PtrTo(Position);
DataItem = Cur->Item;
} // end if
} // end ListRetrieve
7/17/2015
CSCD 326
12
LinkedList.cpp continued
void listClass::ListInsert(int NewPosition,
listItemType NewItem,
bool& Success)
{
int NewLength = ListLength() + 1;
Success = bool( (NewPosition >= 1) &&
(NewPosition <= NewLength) );
if (Success)
{ // create new node and place NewItem in it
ptrType NewPtr = new listNode;
Success = bool(NewPtr != NULL);
if (Success)
{ Size = NewLength;
NewPtr->Item = NewItem;
7/17/2015
CSCD 326
13
LinkedList.cpp continued
// attach new node to list
if (NewPosition == 1)
{//insert new node at beginning of list
NewPtr->Next = Head;
Head = NewPtr;
}
else
{ ptrType Prev = PtrTo(NewPosition-1);
// insert new node after node
// to which Prev points
NewPtr->Next = Prev->Next;
Prev->Next = NewPtr;
} // end if
} // end if
} // end if
} // end ListInsert
7/17/2015
CSCD 326
14
LinkedList.cpp continued
void listClass::ListDelete(int Position,
bool& Success)
{
ptrType Cur;
Success = bool( (Position >= 1) &&
(Position <= ListLength()) );
if (Success)
{ --Size;
if (Position == 1)
{ // delete the first node from the list
Cur = Head; // save pointer to node
Head = Head->Next;
}
7/17/2015
CSCD 326
15
LinkedList.cpp continued
else
{
}
}
ptrType Prev = PtrTo(Position-1);
// delete the node after the
// node to which Prev points
Cur = Prev->Next;//save pointer to node
Prev->Next = Cur->Next;
// end if
// return node to system
Cur->Next = NULL;
delete Cur;
Cur = NULL;
} // end if
// end ListDelete
7/17/2015
CSCD 326
16
Insertion into a Linked List
head
cur
A
B
tmp
struct ListNode
{
char Element;
ListNode *Next;
};
7/17/2015
C
D
X
tmp = new ListNode;
tmp->Element = ‘X’;
tmp->Next = cur->Next;
cur->Next = tmp;
CSCD 326
17
Linked List Insertion - other methods
• If ListNode has a constructor which initializes
data elements directly the code becomes:
tmp = new ListNode(‘X’, cur->next);
cur->Next = tmp;
• and tmp is actually no longer needed so the
code becomes:
cur->Next = new ListNode(‘X’, cur->next);
7/17/2015
CSCD 326
18
Linked List Node Deletion
cur
head
A
B
C
tmp
D
X
ListNode *tmp = cur->Next;
cur->Next = cur->Next->Next;
delete tmp;
7/17/2015
CSCD 326
19
Insert and Delete operations on an
empty list
• One problem with the insertion and deletion
methods is that they require special cases
and different actions for first nodes
• The addition of a dummy head node to the
linked list eliminates the special cases
– the header node does not contain any data and its
pointer points to the first data containing node
– an empty list now consists of a head pointer and a
header node with a NULL pointer
7/17/2015
CSCD 326
20
Abstract Data Type List
• We have been referring to linked lists with the
name List
• it is actually just one implementation of the
higher object which is a General List
• A General List could be implemented using
arrays rather than linked lists
• How would that implementation change from
the linked list implementation?
7/17/2015
CSCD 326
21
Criteria for Linked Lists - ACIDS
• One way to decide which General List
implementation is better for a certain problem is
a criterion based on General List operations
• ACIDS test how easily are operations done
–
–
–
–
–
Add
Change
Inspect
Delete
Sort
• Linked lists are better for adding or deleting
items
• Arrays are better for sorting or finding (inspect,
change, delete) items
7/17/2015
CSCD 326
22
Big-O Notation
• Algorithm Complexity (speed) - a method of
comparing algorithm speeds is Big-O notation:
• O(n) (where n is number of items in a list) says number of operations in an algorithm is
directly proportional to number of elements linear time complexity
• O(1) - says number of operations is constant
and not a function of number of elements
• Insertion and deletion in linked lists is O(1)
while in array based lists it is O(n) - constant
time complexity
– since all n items might have to be moved
7/17/2015
CSCD 326
23
Doubly Linked Lists
• Even though each node in a singly linked list
has a well defined predecessor - it is
impossible to move from a node to its
predecessor
• Doubly linked lists solve this problem by
allowing movement in both directions through
a list
• This is accomplished by adding a pointer to
each node which contains the address of the
previous node
7/17/2015
CSCD 326
24
Doubly Linked List Implementation
struct ListNode
{
char Element;
ListNode *Next;
ListNode *Prev;
ListNode( ) : Next(NULL), Prev(NULL) { }
ListNode( const char & C, ListNode *N = NULL,
ListNode *P = NULL) : Element(C), Next(N),
Prev(P){ }
};
7/17/2015
CSCD 326
25
Doubly Linked List Insertion
cur
A
tmp
M
Z
X
// inserting AFTER cur
tmp = new ListNode(‘X’, cur->Next, cur);
cur->Next->Prev = cur;
cur->Next = tmp;
7/17/2015
CSCD 326
26
Doubly Linked List Deletion
A
M
Z
cur
// deleting cur
cur->Next->Prev = cur->Prev;
cur->Prev->Next = cur->Next;
delete cur;
7/17/2015
CSCD 326
27
Header Nodes for DLL’s
• Inserting /deleting first and last nodes are
special cases for doubly linked lists
• a single routine with no conditions can be
used to insert into /delete from doubly linked
lists by adding a dummy header node to both
ends of the list
7/17/2015
CSCD 326
28
Circular Linked Lists
A
•
•
•
•
B
C
D
The last node in the list points to first
Usually no header node is used
A single node list points to itself
Problems can arise when traversing the list to
its end - easy to construct an infinite loop
7/17/2015
CSCD 326
29