Cursor-Based Linked Lists
Cursor-Based Linked Lists
Module 5 Lists, Stacks, and Queues (Part 3) Some programming languages do not provide mechanisms for the dynamic allocation and deallocation of persistent storage (that is, storage for which allocation and deallocation is not directly related to procedure or function entry and exit). Also, in some systems, the overhead required to use dynamic storage allocation is excessively expensive (in terms of time). In these cases, an alternate method for implementing dynamic storage management is useful. This is sometimes called the cursor method.
2
In the cursor implementation, we build the storage pool ourselves, storing our unused nodes in a linked list stored in an array.
3
The cursor implementation will normally obtain a fixed amount of storage from the system as an array, and provide functions similar to new and delete for an application program to use.
4
When the application requests a new node, one is removed from the head of the storage pool list. If the list is empty, zero is returned (indicating allocation failure). Unneeded nodes are added back to the list, typically at the front (for speed).
5
Note that operations are only permitted at the top of the stack, which is equivalent to one end of the list. Stacks are frequently called LIFO (last in, first out), since the last item pushed on a stack will be the first item removed by a pop operations. It is sometimes useful to provide an additional operation to determine if a stack is empty.
6
Stack Implementations
Stacks can easily be implemented using linked lists:
Push and pop operations are equivalent to insert and retrieve/delete operations on the node in the first position. Testing for an empty stack is equivalent to testing for an empty list.
Stacks can also easily be constructed using a statically allocated array, with an integer variable (e.g. top) indicating the subscript of the first unused location beyond the top of the stack. The basic operations are simple:
Push: stack[top++] = element; Pop: element = stack[--top]; isEmpty: top == 0
Tests for an empty stack prior to popping, and for a full stack prior to push (in an array implementation) are highly recommended.
7
The algorithm for checking a string for symbol balance is simple, and only requires the use of a single stack of characters.
8
Once all characters in the string have been processed, the stack should be empty. If it is not empty, report an error.
Process the elements (numeric values and operators) in the postfix expression from left to right.
When a numeric value is encountered, push it on the stack. When an operator is encountered, pop two values from the stack, apply the operator, and push the resulting value. If at least two values are not on the stack, an error is reported.
Action Push Push Pop 2 & 1, add, push Push Push Pop 4 & 3, add, push Pop 7 & 3, multiply, push 1
Stack
21 3 33 433 73 21
12
When all expression elements have been processed, exactly one value should remain on the stack, and this is the result of the expressions evaluation. We have assumed binary (two-operand) operators here, but postfix notation can also accommodate unary (oneoperand) and operators with more than two operands.
11
At the end of the expression, pop and output operators until the stack is empty.
14
Action Push Output Push Output Pop, output, pop Push Push Output Push Output Pop, output, pop Pop, output
Stack (
Output 1
+( +( ( ( +( +(
16
As expected, the running times for these operations are all O (1) for linked list or array implementations.
18
17
Initialization of the queue is performed by setting size, front, and rear to 0. An additional operation, isFull, may be used to determine if the space available for the queue has been exhausted.
With continual addition of elements to one end and removal of elements from the other end, cause the region of the array occupied by elements will shift, so eventually the value of rear becomes equal to the size of the array, even though size may be small. One solution to this problem is to continually move the elements down in the array, so the element at the front of the queue has the subscript zero. Unfortunately, this is a poor solution, since the running time now becomes O (N ).
20
19
Networks individual messages arrive at a routing point from multiple sources, and need to be queued for retransmission to another destination if the channel to that destination is being used.
22
23