


Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
An introduction to linked lists as an alternative to vectors for organizing collections. It explains the concept of a linked list, its memory representation, and the implementation of a stack using linkedlist. The document also includes exercises for the reader to test their understanding.
Typology: Exams
1 / 4
This page cannot be seen from the preview
Don't miss anything!



The Vector is not the only way to organize a collection. A weakness of the Vector is that elements are stored in a contiguous block. As a consequence, when a new element is inserted into the collection, all the adjacent elements must be moved in order to make space for the new value. An alternative approach is to use the idea of a Linked List. In a linked list each value is stored in a separate block of memory, termed a link. In addition to a value, each link contains a reference to the next link in sequence. As a data structure, a link can be described as shown at right. We can visualize collection formed out of links as follows. A data field named firstLink will hold the first link in the collection. Each link refers to the next. The final link will have a null value in the next field: The simplest data structure to create using links is a Stack. When a new element is pushed on the stack a new link will be created and placed at the front of the chain. To remove a link the variable firstLink is simply changed to point to the next element in the chain. The space for the Link is then freed. struct link { EleType value; struct link * next; };
The following is the beginning of an implementation of a LinkedListStack based on these ideas. Complete the implementation. Each operation should have constant time performance. Use an assertion to ensure that when a top or pop is performed the stack has at least one element. When you pop a value from the stack, make sure you free the link field. struct link { EleType value; struct link * next; }; struct linkedListStack { struct link *firstLink; } void linkedListStackCreate (struct linkedListStack *s) { s->firstLink = 0; } void linkedListStackDestroy (struct linedListStack *s) { while (! linkedListStackIsEmpty(s)) linkedListStackPop(s); } void linkedListStackPush (struct linkedListStack *s, double d) { struct link * newLink = (struct link *) malloc(sizeof(struct link)); assert (newLink != 0); } double linkedListStackTop (struct linkedListStack *s) { } void linkedListStackPop (struct linkedListStack *s) { } int linkedListStackIsEmpty (struct linkedListStack *s) { }
the space is freed by calling the associated pop routine. The user of the list allocates space for the data value, and must therefore ensure that the field is freed when no longer needed. When ever you create a dynamically allocated value you need to think about how and when it will be freed. The first paragraph of this lesson pointed out the problem involved in placing a new element into the middle of a vector (namely, that the following elements must then be moved). Linked lists will help solve this problem, although we have not yet demonstrated that in this lesson. For the vector we created a single general-purpose data structure, and then showed how to use that data structure in a variety of ways. In examining the linked list we will take a different approach. Rather than making a single data abstraction, we will examine the idea of the linked list in a variety of different forms. In subsequent lessons we will examine a number of variations on this idea, such as header or sentinel links, single versus double links, maintaining a pointer to the last as well as the first link, and more. Occasionally you will find links placed directly into a data object. For example, suppose you were creating a card game, and needed a list of cards. One way to do this would be the following: Each card can then be used as a link in a linked list. Although this approach is easy to implement, it should be avoided, for several reasons. It confuses two issues, the management of cards, and the manipulation of the list. These problems should be dealt with independently. It makes your code very rigid; for example, you cannot move the Card abstraction to another program in which cards are not on a list, or must be placed in two different lists at the same time. And finally, you end up duplicating code that you can more easily write once and reuse by using a standard container. struct Card { int suit; int rank; struct Card * next; // link to next card };