Download Doubly linked lists 1 - Richard Kay`s BCU/CEBE Page

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Array data structure wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Red–black tree wikipedia , lookup

Quadtree wikipedia , lookup

Binary tree wikipedia , lookup

Interval tree wikipedia , lookup

Binary search tree wikipedia , lookup

B-tree wikipedia , lookup

Linked list wikipedia , lookup

Transcript
Linked Lists
Source: presentation based on notes written by R.Kay, A. Hill and C.Noble
Lists in general
● Lists indexed using pointer arrays
● Singly linked lists using array storage
● Conventional linked list diagrams
● Data structure for a linked list node
● Inserting a node in a singly linked list
● Deleting a node in a singly linked list
● Traversing a list and finding keys
● Doubly linked lists
●
Lists in general 1
A list is an ordered sequence of items. Previous examples have used
a one-dimensional array or 'vector' to store a list, each element of
the array typically being a record containing data on an item. For
example the following array, in 'C', could store a list of students
and their marks.
Typedef struct person { char name[21];int mark;} PERSON;
PERSON student[100];
Lists in general 2
The order of items stored in a list using an array is determined
by the sequential positioning of the items in memory, ie consecutive items in the list are stored in consecutive memory
locations.
The use of a static array implies that the list will have a fixed
maximum size determined by the variable declaration. This
means that the maximum size must be determined in advance
and the program written to allow for this even though it may
frequently use only a small portion of the array. Alternatively
space for a dynamic array can be calculated and allocated at
runtime using malloc() before storing the items if the number
of records is already known.
Lists in general 3
A more important problem is met when one attempts to add an item
to the list whilst preserving the order of the items. for example, to
add the name BOB to the following list, it is necessary to copy
each array element from student [3] onwards up one position in
order to insert the new record. This problem was met when studying the Insertion Sort algorithm. A similar problem exists when
deleting records from the list.
Lists indexed using pointer array 1
If each data element is large then the amount of unused space in
an array may be considerable, particularly if the array has to
be large enough to anticipate possible maximum use. Inserting, deleting or sorting data elements in the array will require
a large movement of data which will slow the operation of the
program. These problems can be alleviated by using 'dynamic
data structures and storing their locations in an array. The
problem of determining the maximum size of the pointer array is still present but this will be considerably less than than
that of an array of data structures. Inserting, deleting or sorting data elements in the array will now require the movement
and manipulation of pointers which will be faster.
Lists indexed using pointer array 2
The data storage to the right of the drawing can more flexibly
be allocated independently per record as needed using the
malloc() function.
Singly linked lists using array or
dynamic storage 1
A linked list allows data to be inserted into and deleted from a list without physically moving any
data. Additionally, if the linked list is implemented using dynamic data structures the list size can
vary as the program executes.
Each data element or 'node' contains an address
pointer. Consecutive items are not necessarily
stored in order or in consecutive memory locations.
Singly linked
lists using
array or
dynamic
storage 2
The 2 top diagrams
represent the same
data structure.
Neither is more efficient.
Insertion requires
moving indexes, not
moving data.
Singly linked lists using array storage 3
The bottom 2 diagrams on the previous slide show a node for Bob
(mark 62) being inserted into the linked list in alphabetical order.
Each node contains the address of the node that follows it in the
list. So the nodes can be stored anywhere in memory. The last
node in the list contains a special address that indicates that there
are no further nodes. This sentinel value could be -1 instead of an
array index, or NULL in place of a pointer.
The advantage of a linked list over an array becomes apparent
when an item is added to the list. Since the physical location of
each node does not determine its logical position in the list, there
is no need to move any data. All that is required is to alter one or
more of the address pointers.
Conventional
linked list
diagrams 1
Conventional linked list diagrams 2
Although the items stored in a linked list are in order, it is only possible
to perform a sequential search of the list. A search must start with the
first node and proceed sequentialy from one node to the next.
If dynamic memory allocation is used, the space occupied by the deleted node must be freed to avoid a memory leak.
Data structure for a linked list node
Each cell in a linked list will be a structured object. One (or more) data
members (fields) will contain data, and one member will be a pointer to
another similar structured object.
Thus a structure to store data on a student's name and mark could be declared using:
typedef struct cell {
char name[21]; int mark; struct cell *next;
} ITEM;
To create dynamic variables requires the use of a pointer variable to indicate the position of the first structured object. Two further pointer
variables are required to insert and delete other structured objects in the
list. These are declared as follows:
ITEM *p,*q,*first;
Creating a new list 1
To create the first structured object function malloc() is
used.
first = (ITEM*)malloc(sizeof(ITEM));
first->next = NULL;
Function malloc() requires an integer parameter, in this
case k, for the number of bytes required, in this case the
size of structure item. The void pointer returned by malloc() has to be cast to (ITEM*), to make it into a pointer
for the correct type of data. The pointer member next of
structure variable first is assigned the value NULL, a
constant defined in stdio.h as value 0.
Creating a new list 2
It is often convenient to have a dummy node as the first
item in the list to avoid having to process the first node
separately from the remainder. This dummy node contains no data.
Inserting a node in a singly linked list 1
insert(ITEM *p,ITEM *q){
q->next=p->next;
p->next=q;
}
Before this function is called, the new node must
exist and the address of the node before the insert
point must be known. This function is more complicated if there is no dummy node at the front of
the list.
Inserting a node in a singly linked list 2
When insert() is called, *p is assigned the address
of the node before the insert position and *q is
similarly pointed at the node to be inserted.
Inserting a node in a singly linked list 3
The next pointer of
the new node is assigned the address
of the following
node.
The next pointer on
the preceding node
is made to point at
the new node.
Deleting a node in a singly linked list 1
delete(ITEM *p){
ITEM *q;
q=p->next;
p->next=q->next;
free(q);
}
The parameter *p points to the node before the
node to be deleted.
Deleting a node in a singly linked list 2
When delete() is called,
*p is assigned the address of the node before the delete position
and *q is declared as
an ITEM pointer.
q is assigned the address
of the node to be deleted, which is stored
in the next pointer of
the preceding node.
Deleting a node in a singly linked list 3
The next pointer of the
node before the one
to be deleted is pointed at the node after
the one to be deleted.
The memory occupied
by the node to be deleted is freed for reuse to avoid a
memory leak.
Traversing a linked list
void display(ITEM *p){ /* display all nodes in SLL */
/* print headings */
printf("\n%-20s%5s\n","name","mark");
printf("\n%-20s%5s\n","----","----");
while (p->next!=(ITEM*) NULL){
/* loops until last node displayed */
p=p->next; /* first item doesn't contain data, last does */
printf("%-20s%5d\n",p->name,p->mark);
}
}
Finding keys in a linked list
A similar function is used to traverse a SLL in order to find the address of
a data item. Finding nodes before this target point for insertion while
maintaining a sort order or required for a deletion is left as an exercise
for the student.
ITEM *find(ITEM *p, char *searchkey){
/* find node in SLL with name same as searchkey */
while (p->next!=(ITEM*) NULL){
/* loop until last node displayed */
p=p->next; /* first item doesn't contain data, last does */
if(strcmp(p->name,searchkey)==0)
return p;
/* return address of node found with same name */
}
return (ITEM*) NULL; /* search key not in SLL*/
}
Doubly linked lists 1
A doubly linked list contains both a forward pointer and a
backward pointer; i.e. it contains the address of the preceding
and the following nodes.
A doubly linked list occupies slightly more storage space, and
it is more complex to add or delete nodes since twice as many
address pointers have to be manipulated. However, it can be
traversed in either direction enabling both the node preceding
and the node following a given node to be located.
Doubly linked lists 2
A doubly linked list node to store data on a student's name and mark could be declared using:
struct node {
char name[21];
int mark;
struct node *next, *prev; /* pointers to next
and previous nodes */
};
typedef struct node ITEM;
Doubly linked lists 3
In this diagram, we have a doubly linked list in its
initial state with a single dummy node at the head.
Doubly linked
list node
insertion 1
q->next=p->next;
p->next=q;
Doubly linked
list node
insertion 2
p=q->next;
q->prev=p->prev;
p->prev=q;
Doubly linked list node deletion
This is left as an exercise for the student. You are recommended to use a search function to identify the address of
the node to be deleted and then to pass this address to the
delete function. The previous and next nodes can be identified using the forward and back pointers on the node to
be deleted. The forward and back pointers within the
node to be deleted need to be assigned to the previous
and next nodes. The node to be deleted then needs to be
freed to avoid leaking memory.
The older HTML version of these notes contains some
drawings to illustrate these actions.