You are on page 1of 18

Linked Lists

Avoid the drawbacks of fixed size arrays with


Growable arrays
Linked lists
Growable arrays
Avoid the problem of fixed-size arrays
Increase the size of the array when needed
(I.e. when capacity is exceeded)
Two strategies:
tight strategy (add a constant): f(N) = N + c
growth strategy (double up): f(N) = 2N

Tight Strategy
Add a number k (k = constant) of elements
every time the capacity is exceeded


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
C0 + (C0+k) + (C0+Sk) =
S = (N C0) / k
Running time?
C0 * S + S*(S+1) / 2 O(N
2
)
Growth Strategy
Double the size of the array every time is
needed (I.e. capacity exceeded)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
C0 + (C0 * 2) + (C0*4) + + (C0*2
i
) =
i = log (N / C0)
Running time?
C0 [1 + 2 + + 2
log(N/C0)
] O(N)
How does the previous
code change?
Linked Lists
Avoid the drawbacks of fixed size arrays with
Growable arrays
Linked lists
int i, *pi;
float f, *pf;
pi = (int *) malloc(sizeof(int));
pf = (float *) malloc (sizeof(float));
*pi =1024;
*pf =3.14;
printf(an integer = %d, a float = %f\n, *pi, *pf);
free(pi);
free(pf);
request memory
return memory
Using Dynamically
Allocated Memory (review)
bat cat sat vat NULL
Linked Lists
bat cat sat vat NULL
mat
Insertion
Compare this with the insertion in arrays!
bat cat
sat
vat NULL mat
dangling
reference
Deletion
List ADT
ADT with position-based methods
generic methods size(), isEmpty()
query methods isFirst(p), isLast(p)
accessor methods first(), last()
before(p), after(p)
update methods swapElements(p,q),
replaceElement(p,e)
insertFirst(e), insertLast(e)
insertBefore(p,e), insertAfter(p,e)
removeAfter(p)
typedef struct node, *pnode;
typedef struct node {
char data [4];
pnode next;
};
Creation
pnode ptr =NULL;
Testing
#define IS_EMPTY(ptr) (!(ptr))
Allocation
ptr=(pnode) malloc (sizeof(node));
Declaration
Implementation
b a t \0 NULL

address of
first node
ptr data
ptr link
ptr
e name (*e).name
strcpy(ptr data, bat);
ptr link = NULL;
Create one Node
pnode create2( )
{
/* create a linked list with two nodes */
pnode first, second;
first = (pnode) malloc(sizeof(node));
second = ( pnode) malloc(sizeof(node));
second -> next= NULL;
second -> data = 20;
first -> data = 10;
first ->next= second;
return first;
}
10 20 NULL
ptr
Example: Create a two-nodes list
void insertAfter(pnode node, char* data)
{
/* insert a new node with data into the list ptr after node */
pnode temp;
temp = (pnode) malloc(sizeof(node));
if (IS_FULL(temp)){
fprintf(stderr, The memory is full\n);
exit (1);
}


Insert (after a specific position)
strcpy(temp->data, data);
if (node) { noempty list
temp->next=node->next;
node->next= temp;
}
else { empty list
temp->next= NULL;
node =temp;
}
}


50
10 20 NULL
temp
node
10 20 NULL 50
20 NULL
50
node trail = NULL node
(a) before deletion (b)after deletion




Deletion
Delete node other than the first node
10 20 NULL 50
20 NULL
10
head node head
void removeAfter(pnode node)
{
/* delete what follows after node in the list */
pnode tmp;
if (node) {
tmp = node -> next;
node->next = node->next->next;
free(tmp);
}
}

10 20 NULL 50
20 NULL
10
node
void traverseList(pnode ptr)
{
printf(The list contains: );
for ( ; ptr; ptr = ptr->next)
printf(%4d, ptr->data);
printf(\n);
}


Traverse a list
Where does ptr point after this function call?

You might also like