DS4 PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 102

Linked List

Limitations of Dynamic Array


200
201
202

Heap Memory
Limitations of Dynamic Array
Heap Memory (Horizontal View)
200

202
201
Limitations of Dynamic Array
Heap Memory (Horizontal View)
200

202
201

• Memory Manager (A part of operating systems)


manages the memory.

• Keeps track of free space

• Allocates space on request from the programs


Limitations of Dynamic Array
Heap Memory (Horizontal View)
200

202
201

Consider a program segment:

int *p=(int*)malloc(3*sizeof(int));
Limitations of Dynamic Array
Heap Memory (Horizontal View)

212
200

202
201

p
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


Limitations of Dynamic Array
Heap Memory (Horizontal View)

212
200

202
201

p
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
Limitations of Dynamic Array
Heap Memory (Horizontal View)

212
213

220
200

202
201

p q
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
Limitations of Dynamic Array
Heap Memory (Horizontal View)

212
213

220
200

202
201

p q
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
Limitations of Dynamic Array
Heap Memory (Horizontal View)

212
213

220
200

202
201

p q
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
Limitations of Dynamic Array
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

p q r
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
Limitations of Dynamic Array
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

p q r
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
free(q)
Limitations of Dynamic Array
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

p r
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
free(q)
Limitations of Dynamic Array
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

p r
Consider a program segment:

int *p=(int*)malloc(3*sizeof(int)); // int size is 4 bytes


float *q=(float*)malloc(sizeof(float)); // float size is 8 bytes
int *r=(int*)malloc(4*sizeof(int)); // int size is 4 bytes
free(q)
int *s=(int*)malloc(3*sizeof(int)); // int size is 4 bytes
Although free memory is more than required 3 x 4 = 12 bytes, yet it
cannot be allocated as it is not contiguous. Returns a null pointer.
Solution: Linked List
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

Suppose we need to store a list of 4 integers: 7, 10, 5, 9.

Instead of asking memory manager for an integer array of 4 elements,


these 4 integers can be stored one at a time in memory in different
places.
Solution: Linked List
Heap Memory (Horizontal View)

236
212
213

220
221
200

202
201

p
Suppose we need to store a list of 4 integers: 7, 10, 5, 9.

int *p=(int*)malloc(sizeof(int)); *p=7;


Solution: Linked List
Heap Memory (Horizontal View)

7 10

236
212
213

222
200

202
201

p q
Suppose we need to store a list of 4 integers: 7, 10, 5, 9.

int *p=(int*)malloc(sizeof(int)); *p=7;


int *q=(int*)malloc(sizeof(int)); *q=10;
Solution: Linked List
Heap Memory (Horizontal View)

7 5 10

236
212
213

222
200

202
201

p r q
Suppose we need to store a list of 4 integers: 7, 10, 5, 9.

int *p=(int*)malloc(sizeof(int)); *p=7;


int *q=(int*)malloc(sizeof(int)); *q=10;
int *r=(int*)malloc(sizeof(int)); *r=5;
Solution: Linked List
Heap Memory (Horizontal View)

7 5 10 9

233
212
213

222
200

202
201

p r q s
Suppose we need to store a list of 4 integers: 7, 10, 5, 9.

int *p=(int*)malloc(sizeof(int)); *p=7;


int *q=(int*)malloc(sizeof(int)); *q=10;
int *r=(int*)malloc(sizeof(int)); *r=5;
int *s=(int*)malloc(sizeof(int)); *s=9;

Non-contiguous allocation: Hence it is not possible to traverse the list


directly as done in array.
Solution: Linked List
Heap Memory (Horizontal View)

7 5 10 9

233
212
213

222
200

202
201

p r q s
To traverse the elements of the list, one should store the address of the
next element in the list with each element.
Solution: Linked List
Heap Memory (Horizontal View)

7 222 5 233 10 213 9 -1

233
213

222
202

p
To traverse the elements of the list {7, 10, 5, 9}, one should store the
address of the next element (pointer to next element) in the list with
each element.

It is sufficient to know the address of (pointer to) the first node (also
called as head node) to retrieve all the elements of the list.

The last node points to null (represented by -1 here).


Logical View of Singly Linked List
A linked list contains a sequence of nodes.

7 10 5 9
Head pointer Head node

Each node contains a value.

Each node contains the address (link) of the next node.

The last node contains a null link.

The list is identified by a head pointer (link to the head node)


Linked List Approach
• Main problem of array is the slow deletion/insertion since it has
to shift items in its contiguous memory
• Solution: linked list where items need not be contiguous with
nodes of the form item next
ai

• Sequence (list) of four items < a1,a2 ,a3 ,a4 > can be represented
by:

head represents
null

a1 a2 a3 a4
Pointer-Based Linked Lists

• A node in a linked list is usually a struct


struct Node
{ int item; A node

Node *next;
}; //end struct
• A node is dynamically allocated
Node *p;
p = malloc(sizeof(Node));
Pointer-Based Linked Lists
• The head pointer points to the first node in a
linked list
• If head is NULL, the linked list is empty
– head=NULL
• head=malloc(sizeof(Node))
A Sample Linked List
Traverse a Linked List
• Reference a node member with the ->
operator
p->item;
• A traverse operation visits each node in the
linked list
– A pointer variable cur keeps track of the current
node
for (Node *cur = head;
cur != NULL; cur = cur->next)
x = cur->item;
Traverse a Linked List

The effect of the assignment cur = cur->next


Delete a Node from a Linked List
• Deleting an interior/last node
prev->next=cur->next;

• Deleting the first node


head=head->next;

• Return deleted node to system


free(cur);
Delete a Node from a Linked List

Deleting a node from a linked list

Deleting the first node


Insert a Node into a Linked List

• To insert a node between two nodes


newPtr->next = cur;
prev->next = newPtr;

Inserting a new node into


a linked list
Insert a Node into a Linked List

• To insert a node at the beginning of a linked


list
newPtr->next = head;
head = newPtr;

Inserting at the beginning of


a linked list
Insert a Node into a Linked List

• Inserting at the end of a linked list


newPtr->next = cur;
prev->next = newPtr;

Inserting at the end of a


linked list
Look up
BOOLEAN lookup (int x, Node *L)
{ if (L == NULL)
return FALSE
else if (x == L->item)
return TRUE
else
return lookup(x, L-next);
}
An ADT Interface for List
• Functions • Data Members
– isEmpty – head
– getLength – Size
– insert • Local variables to
– delete member functions
– Lookup – cur
– … – prev
Doubly Liked Lists
• Frequently, we need to traverse a sequence in
BOTH directions efficiently
• Solution: Use doubly-linked list where each node
has two pointers
forward traversal

Doubly Linked List. next


head x1 x2 x4
x3
prev

backward traversal
Doubly Linked Lists

• A node in a doubly linked list is usually a struct


struct Node A node
{ int item;
Node *prev;
Node *next;
prev item next
}; //end struct
• A node is dynamically allocated
Node *p;
p = malloc(sizeof(Node));
Inserting a Node
• Insert a node in the middle (After cur)
head x1 x2 x4
x3

cur

newPtr
newPtr->next = cur->next;
newPtr->prev = cur;
cur->next->prev = newPtr;
cur->next = newPtr;
Deleting a Node
• Delete a node from middle

head x1 x2 x4
x3

cur

cur->prev->next = cur->next;
cur->next->prev = cur->prev;
free(cur);
Circular Linked Lists
• May need to cycle through a list repeatedly, e.g.
round robin system for a shared resource.

• Solution: Have the last node point to the first


node (Head).

Circular Linked List.


head x1 x2 ... xn
Try in Lab
• Insert a node into a sorted linked lists at the
correct position.

• Concatenate two singly linked lists.

• Concatenate two doubly linked lists.

• Concatenate two circular linked lists.


Array Vs. Linked LIst
Cost of Accessing ith Element

Array Linked List

Accessed by index Accessed by traversing


Constant Best case: O(1)
O(1) Average/Worst case: O(n)
Array Vs. Linked LIst
Memory Requirement

Array Linked List


Fixed size No unused memory
3 7 4 - - Extra space for pointers
- Negligible if data part is big
Unused
Suffers from fragmentation. Suffers less from fragmentation.
- Contiguous Memory may - Small blocks are likely
not be available to be available
Array Vs. Linked LIst
Cost of inserting an element

Array Linked List

No traversal but shifting Traversal but no shifting

Beginning – O(n) Beginning – O(1)


Middle – O(n) Middle – O(n)
End – O(1) // If array is not full End – O(n)
O(n) // If array is full
// Reallocation required
Array Vs. Linked LIst
Cost of deleting an element

Array Linked List

No traversal but shifting Traversal but no shifting

Beginning – O(n) Beginning – O(1)


Middle – O(n) Middle – O(n)
End – O(1) // If array is not full End – O(n)
Array Vs. Linked LIst
Ease of Use

Array Linked List

Easy to implement Complex use of pointers

Care should be taken to


free up the memory for
deleted nodes.
Polynomial Representation

• What is it?

An example of a single variable polynomial:

4x6 + 10x4 - 5x + 3

4x6 + 0.x5 + 10x4 + 0.x3 + 0.x2 + (-5)x1 + 3x0

Remark: the order of this polynomial is 6


(look for highest exponent)
Polynomial ADT

• Why call it an Abstract Data Type (ADT)?

A single variable polynomial can be generalized


as:
Polynomial ADT (continued)

…This sum can be expanded to:

anxn + a(n-1)x(n-1) + … + a1x1 + a0

Notice the two visible data sets namely: (C and E),


where

• C is the coefficient set [Real values: a0 to an].

• E is the exponent set object [Integer values: 0 to n].


Polynomial ADT (continued)

• Now what?

By definition of a data types:

A set of values and a set of allowable


operations on those values.

We can now operate on this polynomial the


way we like…
Polynomial ADT (continued)

• What kinds of operations?

Here are the most common operations on a


polynomial:
• Add & Subtract
• Multiply
• Differentiate
• Integrate
• etc…
Polynomial ADT (continued)

• Why implement this?

Calculating polynomial operations by hand can


be very cumbersome. Take differentiation as an
example:

d(23x9 + 18x7 + 41x6 + 163x4 + 5x + 3)/dx

= (23*9)x(9-1) + (18*7)x(7-1) + (41*6)x(6-1) + …


Polynomial ADT (continued)

• How to implement this?

There are different ways of implementing the


polynomial ADT:

• Array (not recommended)

•Linked List (preferred and recommended)


Polynomial ADT (continued)
•Array Implementation:
• p1(x) = 8x3 + 3x2 + 2x + 6
• p2(x) = 23x4 + 18x - 3
p1(x) p2(x)

6 2 3 8 -3 18 0 0 23
0 2 0 2 4

Index
represents
exponents
Polynomial ADT (continued)
•This is why arrays aren’t good to represent
polynomials:

• p3(x) = 16x21 - 3x5 + 2x + 6

6 2 0 0 -3 0 ………… 0 16
0 1 2 3 4 5 20 21

WASTE OF SPACE!
Polynomial ADT (continued)
• Advantages of using an Array:

• only good for non-sparse polynomials.


• ease of storage and retrieval.

• Disadvantages of using an Array:

• have to allocate array size ahead of time.


• huge array size required for sparse
polynomials. Waste of space and runtime.
Polynomial ADT (continued)
• Sparse Polynomial

• p4(x) = 6x102 - 13x14 + 22x2 -2

-2 0 22 … … -13 … ... … 0 6
0 1 2 3 ---------13 14 15 ---------------100 101 102

Huge wastage of space


Polynomial ADT using Linked List

Node Representation

struct polynode
{
double coeff;
int expon;
polynode* next;
};
typedef struct polynode *polyptr;

coeff expon next


Polynomial ADT (continued)

• Linked list Implementation:

• p1(x) = 23x9 - 18x7 + 41x6 + 163x4 - 3


• p2(x) = 4x6 + 10x4 - 12x + 8

P1 23 9 -18 7 41 6 163 4 -3 0

TAIL (contains pointer)

P2 4 6 10 4 -12 1 8 0

NODE (contains coefficient & exponent)


Polynomial ADT (continued)
• Advantages of using a Linked list:

• save space (don’t have to worry about sparse


polynomials) and easy to maintain

• don’t need to allocate list size initially and can


declare nodes (terms) only as needed
Adding Two Polynomials (Linked Lists)
• Given two polynomials:

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 - 8x7 + 163x4 + 5


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9
Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 + (-18+10)x7


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 -8x7


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 - 8x7 + 163x4


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 - 8x7 + 163x4 + (-3+8)


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 - 8x7 + 163x4 + 5


Adding Two Polynomials (Linked Lists)
• How it works

p1(x) = 23x9 - 18x7 + 163x4 - 3

p2(x) = 4x8 + 10x7 + 8

After addition

p3(x) = 23x9 + 4x8 - 8x7 + 163x4 + 5


Polynomial ADT (continued)
• Adding polynomials using a Linked list representation: (storing the
result in p3)

To do this, we have to break the process down to cases:


• Case 1: exponent of p1 > exponent of p2
• Copy node of p1 to end of p3.
• p1 = p1->next;
• Case 2: exponent of p1 < exponent of p2
• Copy node of p2 to end of p3.
• p2 = p2->next;
• Case 3: exponent of p1 = exponent of p2
• Create a new node in p3 with the same exponent and with the
sum of the coefficients of p1 and p2.
• p1 = p1->next; p2=p2->next;
Polynomial ADT (continued)
• Adding polynomials using a Linked list representation: (storing the
result in p3)

To do this, we have to break the process down to cases:


• Case 4: p1 == NULL
• Copy entire p2 to end of p3.
• Case 5: p2 == NULL
• Copy entire p1 to end of p3.
Example
14 8
p1  3x  2x 1

p1 3 14 2 8 1 0 null

14 10 6
p2  8x  3x 10x
p2 8 14 -3 10 10 6 null
Adding Two Polynomials
3 14 2 8 1 0
p1

8 14 -3 10 10 6
p2
p1->expon == p2->expon

11 14
p3
Adding Two Polynomials
3 14 2 8 1 0
p1

8 14 -3 10 10 6
p2
p1->expon < p2->expon

11 14 -3 10
p3
Adding Two Polynomials
3 14 2 8 1 0
p1

8 14 -3 10 10 6
p2
p1->expon > p2->expon

11 14 -3 10 2 8
p3
Adding Two Polynomials
3 14 2 8 1 0
p1

8 14 -3 10 10 6
p2
p1->expon < p2->expon

11 14 -3 10 2 8 10 6
p3
Adding Two Polynomials
3 14 2 8 1 0
p1

8 14 -3 10 10 6

p2 = NULL

11 14 -3 10 2 8 10 6

1 0
14 10 8 6
p 3  11 x  3x  2 x  10 x  x p3
• Home task

Represent a two-variable polynomial using


linked list.

4x10y7 – 10x7y6 + 13x6y6 – 23xy2 + 62


Representing two-variable polynomial

p  11 x 6 y 5  3 x 4 y 7  10 x 2 y  xy

11 -3 10 1
6 5 4 7 2 1 1 1
Representing two-variable polynomial
Another way
p  11 x 6 y 5  3 x 4 x 7  10 x 2 y  xy

y 1 2 3 4 5 6 7
x
1 1 0 0 0 0 0 0
2 10 0 0 0 0 0 0
3 0 0 0 0 0 0 0
4 0 0 0 0 0 0 -3
5 0 0 0 0 0 0 0
6 0 0 0 0 11 0 0

Sparse Matrix
Sparse Matrix Representation
In a sparse matrix, most entries are zeroes:
Sparse Matrix Representation
Many problems require large sparse matrices.

For example, a college may have 1000 students and 500


different courses.

We can have a matrix M of size 1000 x 500, where M(i,j)


represents the marks obtained by student i in course j. If
M(i,j)=0, it means student i has not taken course j.

Each student takes only few courses. This will be sparse


matrix with most of the elements 0.

Store as an ordinary array? 1000 x 500 = 500000 entries


Impractical (usually).
Sparse Matrix Representation using
Linked List
Idea: Only allocate memory for the entries that are non-zero.

Mechanism:

Store each non-zero entry in a node.

Use the heap to get the space for non-zero entries.

Link non-zero entries by row and by column.

Each node will need to know its row number and column
number and (non-zero) value.
An Example Node
For example, row 3 and column 4 (i.e., entry [3,4]) contains 42:

struct Node{
int row, col, value;
Node* NextInCol;
Node* NextInRow;
}
Row and Columns
• A row or a column is a linked list of non-zero
entries.

• We will use plain linked lists (not circular or


doubly-linked) with dummy nodes.

• The dummy header nodes would contain row or


column number 0.

• The dummy trailer nodes would contain row


number numRows+1 or column number
numCols+1.
Example
Searching and Element
• We will need to search for particular rows or
columns.

• Idea: Link together “row 0”, which is a list of


all the available columns, and link together
“column 0”, which is a list of all the available
rows.

• How about dummy nodes for those lists?


Good idea.
Example
General Search Strategy
Search for [R,C] element
• Search down dummy column 0 looking for the row list for
row R (or search across dummy row 0 looking for the
column list for column C).

– If the row list (or column list) doesn’t exist, then all entries in
that row (or column) are 0.

• Then search along row R looking for a node in column C (or


search down column C looking for a node in row R).

• If the node you’re looking for doesn’t exist, then the value
of that entry is 0.

• We always search an ordered list.


Example
Example
Example
Setting a new value
More Example
More Example
Example
Example
Example
Example
Example
Example
Example
• If newValue is 0 and you delete the only non-
zero value in column C, then you have to
delete the column list for column C.

• You might have to delete both the list for row


R and the list for column C.
(Pictures omitted.)

You might also like