0% found this document useful (0 votes)
2 views

class4

Chapter 4 covers various data structures including pointers, singly linked lists, and dynamically linked stacks and queues. It discusses the advantages of linked representations for efficient insertion and deletion, and provides examples of polynomial representation using linked lists. The chapter also includes implementation details for operations such as insertion, deletion, and traversal of linked lists.

Uploaded by

souvikkuar97
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

class4

Chapter 4 covers various data structures including pointers, singly linked lists, and dynamically linked stacks and queues. It discusses the advantages of linked representations for efficient insertion and deletion, and provides examples of polynomial representation using linked lists. The chapter also includes implementation details for operations such as insertion, deletion, and traversal of linked lists.

Uploaded by

souvikkuar97
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 61

Chapter 4 Lists

 Pointers
 Singly Linked Lists
 Dynamically Linked Stacks and Queues
 Polynomials
 Chain
 Circularly Linked Lists
 Equivalence Relations
 Doubly Linked Lists
Pointers (1/5)
 Consider the following alphabetized list of three letter
English words ending in at:
(bat, cat, sat, vat)
 If we store this list in an array
 Add the word mat to this list
 move sat and vat one position to the right before we insert mat.
 Remove the word cat from the list
 move sat and vat one position to the left
 Problems of a sequence representation (ordered list)
 Arbitrary insertion and deletion from arrays can be very
time-consuming
 Waste storage
Pointers (2/5)
 An elegant solution: using linked representation
 Items may be placed anywhere in memory.
 In a sequential representation the order of elements is
the same as in the ordered list, while in a linked
representation these two sequences need not be the
same.
 Store the address, or location, of the next element in
that list for accessing elements in the correct order
with each element.
 Thus, associated with each list element is a node
which contains both a data component and a pointer
to the next item in the list. The pointers are often
called links.
Pointers (3/5)
 C provides extensive supports for pointers.
 Two most important operators used with the pointer type :
& the address operator
* the dereferencing (or indirection) operator
 Example:
If we have the declaration:
int i, *pi;
then i is an integer variable and pi is a pointer to an integer.
If we say:
pi = &i;
then &i returns the address of i and assigns it as the value of pi.
To assign a value to i we can say:
i = 10; or *pi = 10;
Pointers (4/5)
 Pointers can be dangerous
 Using pointers: high degree of flexibility and efficiency, but
dangerous as well.
 It is a wise practice to set all pointers to NULL when they are not
actually pointing to an object.
 Another: using explicit type cast when converting between pointer
types.
 Example:
pi = malloc(sizeof(int));/*assign to pi a pointer to int*/
pf = (float *)pi; /*casts int pointer to float pointer*/
 In many systems, pointers have the same size as type int.
 Since int is the default type specifier, some programmers omit the return
type when defining a function.
 The return type defaults to int which can later be interpreted as a pointer.
Pointers (5/5)
 Using dynamically allocated storage
 When programming, you may not know how much space
you will need, nor do you wish to allocate some vary large
area that may never be required.
 C provides heap, for allocating storage at run-time.
 You may call a function, malloc, and request the amount of
memory you need.
 When you no longer need an area of memory, you may free it by
calling another function, free, and return the area of memory to the
system.
 Example:
request memory

return memory
Singly Linked Lists (1/15)
 Linked lists are drawn as an order sequence of
nodes with links represented as arrows (Figure 4.1).
 The name of the pointer to the first node in the list is the
name of the list. (the list of Figure 4.1 is called ptr.)
 Notice that we do not explicitly put in the values of pointers, but
simply draw allows to indicate that they are there.
Singly Linked Lists (2/15)
 The nodes do not resident in sequential locations
 The locations of the nodes may change on
different runs
ptr

... Null
Link Field

Node
Data Field

chain
Singly Linked Lists (3/15)
 Why it is easier to make arbitrary insertions and
deletions using a linked list?
 To insert the word mat between cat can sat, we must:
 Get a node that is currently unused; let its address be paddr.
 Set the data field of this node to mat.
 Set paddr’s link field to point to the address found in the link
field of the node containing cat.
 Set the link field of the node containing cat to point to paddr.
Singly Linked Lists (4/15)
 Delete mat from the list:
 We only need to find the element that immediately
precedes mat, which is cat, and set its link field to point
to mat’s link (Figure 4.3).
 We have not moved any data, and although the link field
of mat still points to sat, mat is no longer in the list.
Singly Linked Lists (5/15)
 We need the following capabilities to make linked
representations possible:
 Defining a node’s structure, that is, the fields it
contains. We use self-referential structures, discussed
in Section 2.2 to do this.
 Create new nodes when we need them. (malloc)
 Remove nodes that we no longer need. (free)
Singly Linked Lists (6/15)
 2.2.4 Self-Referential Structures
 One or more of its components is a pointer to itself.

 typedef struct list { Construct a list with three nodes


char data; item1.link=&item2;
list *link; item2.link=&item3;
} malloc: obtain a node (memory)
free: release memory
 list item1, item2, item3;
item1.data=‘a’;
item2.data=‘b’; a b c
item3.data=‘c’;
item1.link=item2.link=item3.link=NULL;
Singly Linked Lists (7/15)
 Example 4.1 [List of words ending in at]:
 Declaration
typedef struct list_node *list_pointer;
struct list_node {
char data [4];
list_pointer link;
};
 Creation
list_pointer ptr =NULL;
 Testing
#define IS_EMPTY(ptr) (!(ptr))
 Allocation
ptr=(list_pointer) malloc (sizeof(list_node));
 Return the spaces:
free(ptr);
Singly Linked Lists (8/15)
e -> name  (*e).name
strcpy(ptr -> data, “bat”);
ptr -> link = NULL;
address of ptr data ptr link
first node

 b a t \0 NULL
ptr

Figure 4.4:Referencing the fields of a node(p.142)


Singly Linked Lists (9/15)
 Example 4.2 [Two-node linked list]:
typedef struct list_node *list_pointer; #define IS_FULL(ptr) (!
typedef struct list_node { (ptr))
int data;
When returns NULL if there
list_pointer link;
}; is no more memory.
list_pointer ptr =NULL;
 Program 4.2: Create a two-node list
list_pointer create2( )
{
/* create a linked list with two nodes */
list_pointer first, second;
first = (list_pointer) malloc(sizeof(list_node));
second = (list_pointer) malloc(sizeof(list_node));
second -> link = NULL;
second -> data = 20; ptr
first -> data = 10;
first ->link = second;
return first; 10 
}
20 NULL
Singly Linked Lists (10/15)
• Insertion
 Observation
 insert a new node with data = 50 into the list ptr
after node

ptr 10 20 NULL
node

50

temp
Singly Linked Lists (11/15)
 Implement Insertion:
void insert(list_pointer *ptr, List_pointer node)
{
/* insert a new node with data = 50 into the list ptr after
node */
list_pointer temp;
temp=(list_pointer)malloc(sizeof(list_node));
if(IS_FULL(temp)){
fprintf(stderr, “The memory is full\n”);
exit(1);
}
temp 50
temp->data=50;
Singly Linked Lists (12/15)
if(*ptr){ //nonempty list
temp->link = node->link;
node->link = temp;
}
else{ //empty list
temp->link = NULL;
*ptr = temp;
} ptr
} 10 20 NULL
node

50

temp
Singly Linked Lists (13/15)
 Deletion
 Observation: delete node from the list

ptr trial node

10 50 20 NULL

ptr trial node

10 50 20 NULL

ptr

10 20 NULL
Singly Linked Lists (14/15)
 Implement Deletion:
void delete(list_pointer *ptr, list_pointer trail, list_pointer
node)
{
/* delete node from the list, trail is the preceding node
ptr is the head of the list */
if(trail)
trail->link = node->link;
else
ptr trail node
*ptr = (*ptr)->link;
free(node);
10 50 20 NULL
}
Singly Linked Lists (15/15)
 Print out a list (traverse a list)
 Program 4.5: Printing a list
void print_list(list_pointer ptr)
{
printf(“The list contains: “);
for ( ; ptr; ptr = ptr->link)
printf(“%4d”, ptr->data);
printf(“\n”);
}
Dynamically Linked
Stacks and Queues (1/8)
 When several stacks and queues coexisted, there
was no efficient way to represent them
sequentially.
 Notice that direction of links for both stack and the queue
facilitate easy insertion and deletion of nodes.
 Easily add or delete a node form the top of the stack.
 Easily add a node to the rear of the queue and add or delete a
node at the front of a queue.
Dynamically Linked
Stacks and Queues (2/8)
 Represent n stacks Stack

top item link

link

..
.
NULL
Dynamically Linked
Stacks and Queues (3/8)
 Push in the linked stack
void add(stack_pointer *top, element item){
/* add an element to the top of the stack */ Push
stack_pointer temp = (stack_pointer) malloc (sizeof
(stack));
if (IS_FULL(temp)) {
fprintf(stderr, “ The memory is full\n”);
exit(1); temp item link
}
top link
temp->item = item;
temp->link = *top; link
*top= temp;

..
.
} NULL
Dynamically Linked
Stacks and Queues (4/8)
 Pop from the linked stack
element delete(stack_pointer *top) {
/* delete an element from the stack */ Pop
stack_pointer temp = *top;
element item;
if (IS_EMPTY(temp)) {
temp
fprintf(stderr, “The stack is empty\n”);
top item link
exit(1);
} link
item = temp->item;
link
*top = temp->link;

..
.
free(temp);
return item; NULL
}
Dynamically Linked
Stacks and Queues (5/8)
 Represent n queues

Queue
front item link
Delete from
link

..
.
Add to
rear NULL
Dynamically Linked
Stacks and Queues (6/8)
 enqueue in the linked queue

front link
link

..
.
rear NULL

temp item NULL


Dynamically Linked
Stacks and Queues (7/8)
 dequeue from the linked queue (similar to push)

temp
front item link

link
link

..
.
rear NULL
Dynamically Linked
Stacks and Queues (8/8)
 The solution presented above to the n-stack, m-
queue problem is both computationally and
conceptually simple.
 We no longer need to shift stacks or queues to make
space.
 Computation can proceed as long as there is memory
available.
Polynomials (1/9)
 Representing Polynomials As Singly Linked Lists
 The manipulation of symbolic polynomials, has a classic example
of list processing.
 In general, we want to represent the polynomial:

A( x ) am  1 x em  1   a0 x e0
 Where the ai are nonzero coefficients and the ei are
nonnegative integer exponents such that
em-1 > em-2 > … > e1 > e0 ≧ 0 .
 We will represent each term as a node containing coefficient and
exponent fields, as well as a pointer to the next term.
Polynomials (2/9)
 Assuming that the coefficients are integers, the type
declarations are:
typedef struct poly_node *poly_pointer;
typedef struct poly_node {
int coef;
int expon;
a 3 x14  2 x 8  1
poly_pointer link;
};
poly_pointer a,b,d; b 8 x 14  3x 10  10 x 6
 Draw poly_nodes as:
coef expon link
Polynomials (3/9)
 Adding Polynomials
 To add two polynomials,we examine their terms
starting at the nodes pointed to by a and b.
 If the exponents of the two terms are equal
1. add the two coefficients
2. create a new term for the result.
 If the exponent of the current term in a is less than b
1. create a duplicate term of b
2. attach this term to the result, called d
3. advance the pointer to the next term in b.
 We take a similar action on a if a->expon > b->expon.
 Figure 4.12 generating the first three term of
d = a+b (next page)
Polynomials
(4/9)
Polynomials
(5/9)
 Add two
polynomials
Polynomials (6/9)
 Attach a node to the end of a list
void attach(float coefficient, int exponent, poly_pointer *ptr){
/* create a new node with coef = coefficient and expon = exponent,
attach it to the node pointed to by ptr. Ptr is updated to point to
this new node */
poly_pointer temp;
temp = (poly_pointer) malloc(sizeof(poly_node));
/* create new node */
if (IS_FULL(temp)) {
fprintf(stderr, “The memory is full\n”);
exit(1);
}
temp->coef = coefficient; /* copy item to the new node */
temp->expon = exponent;
(*ptr)->link = temp; /* attach */
*ptr = temp; /* move ptr to the end of the list */
}
Polynomials (7/9)
 Analysis of padd
A( x )( am  1 x em  1   a0 x e0 )  B( x )( bn  1 x f n  1    b0 x f 0 )

1. coefficient additions
0  additions  min(m, n)
where m (n) denotes the number of terms in A (B).
2. exponent comparisons
extreme case:
em-1 > fm-1 > em-2 > fm-2 > … > e1 > f1 > e0 > f0
m+n-1 comparisons
3. creation of new nodes
extreme case: maximum number of terms in d is m+n
m + n new nodes
summary: O(m+n)
Polynomials (8/9)
 A Suite for Polynomials
e(x) = a(x) * b(x) + d(x) read_poly()
poly_pointer a, b, d, e; print_poly()
... padd()
a = read_poly(); psub()
b = read_poly();
pmult()
d = read_poly();
temp = pmult(a, b);
temp is used to hold a partial result.
e = padd(temp, d); By returning the nodes of temp, we
print_poly(e); may use it to hold other polynomials
Polynomials (9/9)
 Erase Polynomials
 erase frees the nodes in temp
void erase (poly_pointer *ptr){
/* erase the polynomial pointed to by ptr */
poly_pointer temp;
while ( *ptr){
temp = *ptr;
*ptr = (*ptr) -> link;
free(temp);
}
}
Chain (1/3)
 Chain:
 A singly linked list in which the last node has a null link
 Operations for chains
 Inverting a chain
 For a list of length ≧1 nodes, the while loop is executed
length times and so the computing time is linear or O(length).

... NULL

lead
invert

× ...
NULL

lead
Chain
(2/3)

Two extra pointers

lead middle trial

NULL ... NULL


 Concatenates two chains Chain (3/3)
 Concatenates two chains, ptr1 and ptr2.
 Assign the list
ptr1 followed
by the list ptr2.

O(length of list ptr1)

temp

NULL NULL

ptr1 ptr2
Circularly Linked Lists (1/10)
 Circular Linked list
 The link field of the last node points to the first
node in the list.
 Example
 Represent a polynomial ptr = 3x14+2x8+1 as a
circularly linked list.

ptr 3 14 2 8 1 0
Circularly Linked Lists (2/10)
 Maintain an Available List
 We free nodes that are no longer in use so that we
may reuse these nodes later
 We can obtain an efficient erase algorithm for circular
lists, by maintaining our own list (as a chain) of nodes
that have been “freed”.
 Instead of using malloc and free, we now use
get_node (program 4.13) and ret_node (program
4.14).

avail ... NULL

List of freed nodes


Circularly Linked Lists (3/10)
 Maintain an Available List (cont’d)
 When we need a new node, we examine this list.
 If the list is not empty, then we may use one of its
nodes.
 Only when the
list is empty we
do need to use
malloc to
create a new
node.
Circularly Linked Lists (4/10)
 Maintain an Available List (cont’d)
 Insert ptr to the front of this list
 Let avail be a variable of type poly_pointer that points
to the first node in our list of freed nodes.
 Henceforth, we call this list the available space list or
avail list.
 Initially, we set avail to NULL
Circularly Linked Lists (5/10)
 Maintain an Available List
 Erase a circular list in a fixed
amount (constant) of time
O(1) independent of the
number of nodes in the list
using cerase

ptr      

temp

avail      NULL

 紅色 link 所連接而成的 chain


Circularly Linked Lists (6/10)
 We must handle the zero polynomial as a special
case. To avoid it, we introduce a head node into
each polynomial
 each polynomial, zero or nonzero, contains one additional
node.
 The expon and coef fields of this node are irrelevant.

Why ?

So !
Circularly Linked
Lists (7/10)
 For fit the
circular list with /* head node */
head node
representation
 We may remove
the test for (*ptr) /*a->expon=-1, so b->expont > -1 */
from cerase
 Changes the
original padd to
cpadd

/* link to the first node */


Circularly Linked Lists (8/10)
 Operations for circularly linked lists
 Question:
 What happens when we want to insert a new node
at the front of the circular linked list ptr?

ptr x1 x2 x3
 Answer:
 move down the entire length of ptr.
 Possible Solution:

x1 x2 x3 ptr
Circularly Linked Lists (9/10)
 Insert a new
node at the front
of a circular list
 To insert node
at the rear, we
only need to add
the additional
statement *ptr =
node to the else
clause of
insert_front

x1 x2 x3 ptr

node
Circularly Linked Lists (10/10)
 Finding the length of a circular list
Equivalence Relations (1/6)
 Reflexive Relation
 for any polygon x, x ≡ x (e.g., x is electrically equivalent to itself)
 Symmetric Relation
 for any two polygons x and y, if x ≡ y, then y ≡ x.
 Transitive Relation
 for any three polygons x, y, and z, if x ≡ y and y ≡ z, then x ≡ z.
 Definition:
 A relation over a set, S, is said to be an equivalence relation
over S iff it is symmertric, reflexive, and transitive over S.
 Example:
 “equal to” relationship is an equivalence relation
 Example: Equivalence Relations (2/6)
 if we have 12 polygons numbered 0 through 11
0  4, 3  1, 6  10, 8  9, 7  4, 6  8, 3  5, 2  11, 11
0
 we can partition the twelve polygons into the following
equivalence classes:
{0, 2, 4, 7, 11};{1, 3, 5};{6, 8, 9,10}
 Two phases to determine equivalence
 First phase: the equivalence pairs (i, j) are read in and
stored.
 Second phase:
 we begin at 0 and find all pairs of the form (0, j).
Continue until the entire equivalence class containing 0 has been
found, marked, and printed.
 Next find another object not yet output, and repeat
the above process.
Equivalence Relation (3/6)
 Program to find equivalence classes
void main(void){ #include <stdio.h>
short int out[MAX_SIZE]; #define MAX_SIZE 24
node_pointer seq[MAX_SIZE]; #define IS_FULL(ptr) (!(ptr))
node_pointer x, y, top; #define FALSE 0
int i, j, n; #define TRUE 1
printf(“Enter the size (<=%d) ”, MAX_SIZE);
scanf(“%d”, &n);
for(i=0; i<n; i++){ typedef struct node
/*initialize seq and out */ *node_pointer;
typedef struct node {
out[i] = TRUE; seq[i] = NULL;
} int data;
/* Phase 1 */ node_pointer link;
};
/* Phase 2 */
}
Equivalence Relations (4/6)
 Phase 1: read in and store the equivalence pairs <i, j>
[0] 11 4 NULL

[1] 3 NULL

[2] 11 NULL
[3] 5 1 NULL

[4] 7 0 NULL
(1) (2)
[5] 3 NULL Insert x to the top of lists seq[i]
[6] 8 10 NULL
[7] 4 NULL

[8] 6 9 NULL

[9] 8 NULL

[10 6 NULL
Insert x to the top of lists seq[j]
]
[11 0 2 NULL

]
0  4, 3  1, 6  10, 8  9, 7  4, 6  8, 3  5, 2  11, 11  0
Equivalence Relations (5/6)
 Phase 2:
 begin at 0 and find all pairs of the form <0, j>, where 0
and j are in the same equivalence class
 by transitivity, all pairs of the form <j, k> imply that k
in the same equivalence class as 0
 continue this way until we have found, marked, and
printed the entire equivalent class containing 0
Equivalence Relations (6/6)
x
 Phase 2 y [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

top
i= 1
0 j= 11
7
2
4
0 out
:
[0] 11 4 NULL

[1] 3 NULL

[2] 11 NULL
[3] 5 1 NULL

[4] 7 0 NULL

[5] 3 NULL

[6] 8 10 NULL
[7] 4 NULL

[8] 6 9 NULL

[9] 8 NULL

[10 6 NULL

]
[11 0 2 NULL

]
New class: 0 11 4 7 2
Doubly Linked Lists (1/4)
 Singly linked lists pose problems because we
can move easily only in the direction of the links
... NULL

? ptr
 Doubly linked list has at least three fields
 left link field(llink), data field(item), right link field(rlink).
 The necessary declarations:
typedef struct node *node_pointer;
typedef struct node{
node_pointer llink;
element item;
node_pointer rlink;
};
Doubly Linked Lists (2/4)
 Sample
 doubly linked circular with head node: (Figure 4.23)

 empty double linked circular list with head node


(Figure 4.24)

 suppose that ptr points to any node in a doubly


linked list, then:
 ptr = ptr -> llink -> rlink = ptr -> rlink -> llink
Doubly Linked Lists (3/4)
 Insert node

Head node

node

llink item rlink

New node
Doubly Linked Lists (4/4)
 Delete node

Head node

llink item rlink


deleted node

You might also like