Вы находитесь на странице: 1из 65

DATA

STRUCTURES
WEEK 5-6-7

adeelmuzaffar@gmail.com
Outline
• Limitations of Arrays
• Definition
• Basic Operations
• Linked Stack, Queue and Priority Queue
• Implementation in C++
• Circular Linked List
• Doubly Linked List
• Case Study: Long Integers

3
Array Limitations
• Simple and Fast (indexed)
but
• Size fixed at construction time (static)
• Contiguous memory allocation
• Time consuming to do ordered insert
• have to shift lots of other data around

4
Ordered Array Insert
• Consider the following array
0 1 2 3 4 5 6 7 8

a c f m x

• Now assume we want to insert ‘k’


– must then move ‘m’ and ‘x’ down one slot
• this can be very time consuming for large arrays
0 1 2 3 4 5 6 7 8

a c f k m x
Array vs. Linked List
array [0] [1] [2]
Array A B C

node
list
Linked list A B C

•A linked list is a very flexible dynamic data structure


•Linked lists are unbounded

6
Linked List
• Definition
– a linked list is a collection or chain of nodes
– each node references the next node in chain
– last node references null
– Each node of the list contains
info next
• the data
• a pointer to the next node
node
– Head node Æfirst node
– Tail node Æ last node
7
A Linked List
Head Tail

Sara Umer Ali

87.45 87.45 87.45

8
A Node in C++
• Node stores a piece of data
• Node stores a pointer to another node

• Example:

struct Node
{
string name;
float grade;
Node* next;
};
9
Algorithmic Notations
• If p is a pointer to a node then node (p) refers to the
node pointed by p
• info(p) refers to the information portion of that node
• next(p) refers to the next field

p Info next

• p = getnode()
• freenode(p)

10
Inserting a front Node

p=getnode();

info(p) = x;

next(p)=list;

list = p;
11
Deleting the front Node

p= list;

list=next(p);

x= info(p);

freenode(p);
12
Traversing a Linked List

list
42 98 12 6

ptr

13
Traversing a Linked List
// Initialize the pointer ptr
ptr = list;
// traverse the list
while (ptr != NULL)
{
PROCESS info(ptr);
// increment ptr to point to next node
ptr = next(ptr);
}
14
An Example
• The following function finds the total number of nodes in a
linked list.

Count(List, Num)
{
Num = 0;
ptr = List;
while (ptr != NULL)
{
Num = Num+1;
ptr = next(ptr);
}
}
15
Insertion after a node

16
Insertion after a node

insafter(p, x)
{
q=getnode();
info(q)=x;
next(q)=next(p);
next(p)=q;
}
17
Deletion after a node

delafter(p,x)
{ q=next(p);
x=info(q);
next(p)=next(q);
freenode(q); }
18
Linked List in C++
struct node {
int info;
struct node* next; NODEPTR getnode()
}: {
typedef struct node* NODEPTR; NODEPTR p;
p=new node;
void freenode(NODEPTR p)
return(p);
{
}
delete(p);
}
19
Linked Stack and Queue

20
Linked Stack
Top of the Stack

NULL pointer
21
Push
s

22
Push
• create a new node for the item
• save data in the node
• link the new node to the current top node
• make the new node the new top
push (s, x)
{ p = getnode ();
info (p) = x;
next (p) = s;
s = p;
} 23
empty

empty (s)
{
if (s == NULL)
return TRUE;
else
return FALSE;
}

24
Pop
s

25
Pop
• check if the stack is empty
• remember address of current top node
• save the item in the top node
• make the next node the new top
• free the old top node
• return the item

26
Pop
pop (s)
{ if (empty (s))
Write: “Stack Underflow”;
else
{ p = s;
x = info (p);
s = next (p);
freenode (p); }
return x;
}
27
Linked Queue

front rear

28
Insert

front rear

front rear
29
Insertion in a Queue
• create a new node for the item
• if the queue is empty:
– the new node becomes both front and rear of the
queue
• otherwise:
– make a link from the current rear to the new
node
– the new node becomes the new rear

30
Insertion in a Queue
insert (q, x)
{
p = getnode ();
info (p) = x; next (p) = NULL;
if (q.rear == NULL)
q.front = p;
else
next (q.rear) = p;
q.rear = p;
}
31
Delete

front rear

front rear
32
Delete
• check that the queue is not empty
• save the item in the front node
• remember the address of the front node
• make the next node the new front
• free the old front node
• if queue is now empty, set rear to NULL
• return the item

33
Delete
remove (q, x)
{
if (empty (q)) Write: “Underflow”;
else
{
p = q.front;
x = info (p);
q.front = next (p);
if (q.front == NULL)
q.rear = NULL;
freenode (p);
}
}
34
Linked Priority Queue
Place (list, x)
{
q = null;
for (p = list; p != NULL && x > info (p); p = next (p))
q = p;
/* at this point new node must be inserted */
if (q == NULL)
push (list, x);
else
insafter (q, x);
}

35
Header Node
• A special node
• First node
• Global info

36
Linked List Class

37
template<class ItemType>
class List
{
protected:
struct node {
ItemType info;
struct node *next;
};
typedef struct node *NODEPTR;
NODEPTR listptr;
public:
List();
~List();
bool emptyList();
void insertafter(ItemType oldvalue, ItemType newvalue);
void deleteItem(ItemType oldvalue);
void push(ItemType newvalue);
ItemType pop();
};
38
// Default Constructor that initializes a newly created list to empty list.
template<class ItemType>
List<ItemType>::List()
{
listptr = 0;
}

// Destructor traverses the nodes of a list, freeing them one by one.


template<class ItemType>
List<ItemType>::~List()
{
NODEPTR p, q;
if (emptyList())
exit(0);
for (p = listptr, q = p->next; p!=0; p = q, q = p->next)
delete p;
}
39
// Determines if the list is empty.
template<class ItemType>
bool List<ItemType>::emptyList()
{
return (listptr == 0);
}

40
// searches for the first occurance of oldvalue in the list and inserts a
new node with value newvalue following the node containing oldvalue.

template<class ItemType>
void List<ItemType>::insertafter(ItemType oldvalue, ItemType newvalue)
{
NODEPTR p, q;
for (p = listptr; p != 0 && p->info != oldvalue; p = p->next)
;
if (p == 0)
{ cout << " ERROR: value sought is not in the list.";
exit(1);
}

q = new node;
q->info = newvalue;
q->next = p->next;
p->next = q;
}
41
// deletes the first node containing the value oldvalue from the list.
template<class ItemType>
void List<ItemType>::deleteItem(ItemType oldvalue)
{
NODEPTR p, q;
for (q = 0, p = listptr; p != 0 && p->info != oldvalue;
q = p, p = p->next)
;
if (p == 0)
{ cout << " ERROR: value sought is not in the list.";
exit(1);
}
if (q == 0)
listptr = p->next;
else
q->next = p->next;
delete p;
}

42
// push(newvalue) adds a new node with a given value to
the front of the list
template<class ItemType>
void List<ItemType>::push(ItemType newvalue)
{
NODEPTR p;
p = new node;
p->info = newvalue;
p->next = listptr;
listptr = p;
}

43
// pop deletes the first node of the list and returns its
contents
template<class ItemType>
ItemType List<ItemType>::pop()
{
NODEPTR p;
ItemType x;
if (emptyList())
{ cout << " ERROR: the list is empty.";
exit(1); }
p = listptr;
listptr = p->next;
x = p->info;
delete p;
return x;
}
44
Circular Linked List
• The last node points to the first node
first
A B C

• If the linked list points to the last node rather than the first
node, it is very similar to the diagram in the previous slide
last
How do we refer to
A B C
the first node?

45
Circular Lists
list Empty list

list

info One node in list


next

Multiple nodes in list

info info info list

next next next


46
Circular List: Insertion list

Insert (list, x)
{ p = getnode();
info(p) = x;
if (list == null)
list = p;
else
next(p) = next(list);
next(list) = p;
} 47
Circular List: Concatenation
plist1

P O W E R

plist2

P O I N T

48
Circular List Concatenation
NODEPTR concat (NODEPTR plist1, NODEPTR plist2)
{
NODEPTR p;
if (plist2 == NULL)
return plist1;
if (plist1 == NULL)
{ plist1 = plist2;
return plist1;
}
p = plist1onext;
plist1onext = plist2onext;
plist2onext = p;
plist1 = plist2;
return plist1;
}

49
Circular List Application

Josephus Problem
read(n);
read(name);
while(name !=END) { insert name in the circular list;}
while (there is more than one node in the list)
{ count through n-1 nodes in the list;
print the name in the nth node;
delete the n node;
}
print the name of only node in the list
50
Doubly Linked List
A linked list in which each node contains two
pointers (right and left).

Head Tail

Sara Ali Zain

87.45 87.45 87.45

right right right

left left left


51
Doubly Linked List

left right left right left right


head 56 74 25

tail

struct node {
int info; If p is a pointer
node *left,*right; left(right(p)) = p = right(left(p))
};
52
Doubly Linked List: Deletion
q p r
void delete(NODEPTR p, int x)
{ NODEPTR q,r;
if (p==NULL)
cout<<“void deletion”;
x=pÆinfo;
q=pÆleft;
r=pÆright;
rÆleft=q;
qÆright=r;
freenode(p);
}
53
Doubly Linked List: Insertion
p r
void insertright(NODEPTR p, int x)
{
If(p==NULL)
cout <<“void insertion”;
q=getnode();
q
qÆinfo=x;
r=pÆright;
rÆleft=q;
qÆright=r;
qÆleft=p;
pÆright=q;
54
}
Case Study

Long Positive Integers

55
Representation of Long Positive
Integers
• The hardware of most computers allows
integers of only a specific maximum length.
• Suppose we want to represent positive
integers of arbitrary lengths
• To add two such integers, their digits are
traversed from right to left, and the
corresponding digits and a possible carry
from the previous digit's sum are added.
56
Addition of Long Positive integers
• This suggests representing long integers by storing
their digits from right to left in a list so that:
• the first node contains the least significant
digits(rightmost)
• the last node contains most significant digits
(leftmost).

57
Long Integers Example

459763497210698463
459 76349 72106 98463

n 98463 72106 76349 459

58
Addition of Long Positive integers
• To save space we keep five digits in each node
(long int will be used to store numbers as large as
99999).
• To add two such numbers, two list are traversed in
parallel, and five digits are added together.
• If the sum of two five digits numbers is x, the low
order five digits of x are extracted by using the
expression: x % 100000
• The carry can be computed by the integer division:
x / 100000
59
Long Integers Addition Example

459 76349 72106 98463

n1 98463 72106 76349 459

15 43268 99087 80909

n2 80909 99087 43268 15

60
Addition of Long Integers
• Let us consider extending the list implementation of
long integers to include negative as well as positive
integers.

• The header node of the circular list representing the


long integer contains an indication of whether the
integer is positive or negative.

• To add a positive and a negative integer, the smaller


absolute value must be subtracted from the larger
absolute value and the result must be given the sign
of integer with larger absolute value.
61
Addition of Long Integers
• Some method is needed for testing which of the
two integers has larger absolute value.

• The first criterion that may be used is to find the


length of numbers. The list with more nodes
represents integer with larger absolute value.

• But this involves traversing the entire list,


However, this information can be stored in the
header node.

62
Long Integers Addition Example

459 76349 72106 98463


n1

4 98463 72106 76349 459

- 459 43268 99087 80909


n2

-4 80909 99087 43268 459

63
Addition of Long Integers
• If both lists have same number of nodes, the integer
with larger MSD has the greater absolute value. If
the MSDs of both numbers are same then it in
necessary to traverse the list from MSD to LSD.
• Note that this traversal is in direction opposite to
that of the traversal used in actually adding two
integers.
• Since we must be able to traverse the lists in
both directions, doubly linked list are used to
represents such integers.
64
Linked List: Conclusion
• Advantages
– can grow to “infinite” size
• only constrained by the size of memory
– very quick to insert or delete a node
• just move a few references around
• Disadvantage
– more difficult to implement than array
– can be very slow to search and access
• have to access each previous element to get the one desired
• Use a linked list instead of an array when
– the number of data elements is unpredictable
– the list needs to be sorted 65

Вам также может понравиться