Professional Documents
Culture Documents
Chapter XXXIX
Chapter XXXIX
Linked Lists I
Your textbook, Part IV, is titled Abstract Data Structures. Now abstract is nice
and provides many benefits for program design. On the other hand, there comes
the implementation reality check. Sooner or later you need to sit down and start
to put some code on paper, in the computer or somewhere. This chapter is the
first of several chapters that is all about the reality of implementation linked lists.
In the last chapter, you were introduced to the concept of the linked list. You
learned how linked lists are an improvement over lists that requires contiguous
blocks of memory. You saw how linking nodes can be very efficient both in the
area of execution speed and memory allocation.
You also did an assignment that graphically drew some linked lists. Do get used
to something right now. Linked lists can be tricky critters and it is wise to have a
notepad nearby, to draw proctors, when you work with linked lists to insure that
you do not get confused about the organization of the data structure.
It will take two chapters to introduce all the various ways that linked lists can be
implemented. Fundamentally, the concepts are the same. Data needs to be stored
in some data structure. Along with the stored data there is also information that
links the record to some other record located elsewhere in memory. The
allocation of this memory occurs during program execution whenever there is a
need to store additional data.
You may be surprised that this section talks about stacks. After all, are we not
working with linked lists? We certainly are doing linked lists and this section
will explain how to implement the data structure that allows the efficient linking
of nodes. In this first section we will not be concerned with complexities of
inserting and deleting nodes in the middle of a list. Right now the simplest way
to learn about handling links is to concentrate on linking at one end of a linked
list. The end result of building a list at one end only is that the list behaves like a
stack. However, the motivation is to learn the easiest type of linked list
implementation, and this just happens to be a stack. In the previous chapter you
learned how to draw pictures that created a linked list both as a stack and a queue.
The secret of implementing a linked list revolves around a rather peculiar looking
data structure. The struct data structure is a good choice since it allows different
data types. Each node in a linked list needs to store data as well as information
about the next node. A good choice for this “link” is the use of a pointer, which
stores the address of the next node in the list. You have learned that a pointer is
not simply an address, but an address of a memory cell that has the required
number of bytes of the particular type being used. An integer pointer has 2-byte
memory cells, a float pointer has 4-byte memory cells, and a pointer to a data
structure will have the number of bytes required for the entire data structure.
This brings up a curious problem. Each node in the linked list will then contain a
field, which is a pointer to another node. But the pointer is inside the very
structure that it points to. The solution is to use a self-referencing declaration like
the one shown below.
// self-referenced declaration
struct ListNode
{
char Data;
ListNode* Next;
};
ListNode is a data structure with two fields. The first field, Data, is a character
to store necessary information. This field can be any data type, including some
other data structure. The second field, Next, is a pointer and notice that this is a
pointer to ListNode. Normally, it is not possible to make a reference to anything
that is not yet completely declared. This is allowed, in the case of making
reference to some memory location that will be allocated during program
execution.
struct ListNode
{
char Data;
ListNode* Next;
};
This is the type of stuff that often causes major confusion. The only reason why
this self-referential stuff is included is for multiple reading purposes. After you
look at a variety of program examples that use this type of structure, you will see
a pattern that will help to explain what is going on. A second or third time passed
over this page will be a whole lot more agreeable than it is the first time.
It is also important to realize that ListNode, Data, and Next are not special C++
keywords at all. The exact same functionality can be achieved with the following
node declaration.
struct Tiger
{
char Book;
Tiger* Giraffe;
};
The first linked list program example will create a small linked list with only two
nodes. Only characters are stored as data in the linked list besides the linking
information. Graphically, the linked list has the following appearance:
The diagonal line in the picture indicates the NULL pointer or address. It is used
to indicate the end of the list. NULL is a pointer, but it does not point to any
other node. Its only purpose in life is to help identify the end of a list. The value
of NULL is zero (0). Program PROG3901.CPP shows the syntax of this first
program. Every program statement in this example will be explained in detail on
the next page.
// PROG3901.CPP
// This program creates a linked list with two nodes.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
char Data;
ListNode *Next;
};
void main()
{
clrscr();
ListNode *P; // define pointer P
ListNode *Temp; // define temporary pointer Temp
Temp = NULL; // [1]
P = new ListNode; // [2]
P->Data = 'X'; // [3]
P->Next = Temp; // [4]
Temp = P; // [5]
P = new ListNode; // [6]
P->Data = 'Y'; // [7]
P->Next = Temp; // [8]
Temp = P; // [9]
cout << "LIST WITH TWO NODES IS COMPLETE" << endl;
getch();
}
PROG3901.CPP OUTPUT
[5] Temp = P;
P is patiently pointing at the newly created object. Temp is tired of
pointing at NULL, and now points to the same object as P. P->Next is
left, and doomed for now to point at NULL.
The next program example creates the exact same linked list of two nodes. The
reason for the second look is to see the memory address stored by the pointers at
different parts in the program. In particular, it shows how the Next pointer stores
the same address as the P pointer after the nodes are linked together.
// PROG3902.CPP
// This program creates a linked list with two nodes and
// investigates the contents at different memory locations.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
char Data;
ListNode *Next;
};
void main()
{
ListNode *P;
ListNode *Temp;
clrscr();
Temp = NULL; cout << "Temp = " << Temp << endl;
cout << endl;
P = new ListNode; cout << "P = " << P << endl;
P->Data = 'X'; cout << "P->Data = " << P->Data << endl;
P->Next = Temp; cout << "P->Next = " << P->Next << endl;
Temp = P; cout << "Temp = " << Temp << endl;
cout << endl;
P = new ListNode; cout << "P = " << P << endl;
P->Data = 'Y'; cout << "P->Data = " << P->Data << endl;
P->Next = Temp; cout << "P->Next = " << P->Next << endl;
Temp = P; cout << "Temp = " << Temp << endl;
getch();
}
PROG3902.CPP OUTPUT
Temp = 0x0
P = 0x90eb0004
P->Data = X
P->Next = 0x0
Temp = 0x90eb0004
P = 0x90ec0004
P->Data = Y
Program PROG3903.CPP will demonstrate how handy the NULL pointer is.
This program creates a linked list with three nodes in the same manner as the
previous two programs with one extra node added. The new feature is showing
how the linked list is traversed so that each node can be visited when the list is
completed. You and I both know that the list only has three nodes and it would
be simple to use a for loop that repeats three times. It is better to see how a
linked list should be traversed without concern about the number of nodes in the
list. The handy NULL pointer functions as a sentinel to alert the repetition
process to halt. This allows the use of a conditional loop to traverse every node
in the list, regardless of the number of current nodes.
The output execution of the next program should demonstrate that this linked list
has some serious family ties to the stack data structure. The characters X, Y, and
Z are assigned to the nodes in the list and traversing the list displays these three
characters in reverse order.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
char Data;
ListNode *Next;
};
void main()
{
clrscr();
ListNode *P;
ListNode *Temp;
Temp = NULL;
P = new ListNode;
P->Data = 'X';
cout << "Storing P->Data: " << P->Data << endl;
P->Next = Temp;
Temp = P;
P = new ListNode;
P->Data = 'Y';
cout << "Storing P->Data: " << P->Data << endl;
P->Next = Temp;
Temp = P;
P = new ListNode;
P->Data = 'Z';
cout << "Storing P->Data: " << P->Data << endl;
P->Next = Temp;
Temp = P;
cout << endl;
while (P != NULL)
{
cout << "Visiting P->Data: " << P->Data << endl;
P = P->Next;
}
cout << endl;
getch();
}
PROG3903.CPP OUTPUT
Storing P->Data: X
Storing P->Data: Y
Storing P->Data: Z
All the previous linked list programs have rather inefficiently created nodes in a
linked list with program code for each node. This was inefficient but it was
readable and made it easier to understand the relationship between the different
nodes in the linked list. In the next program a linked list of twenty-six nodes will
store every character in the alphabet. Pay particular attention to the statement
Temp = NULL; That statement is not placed inside the loop. Hopefully you
realize that this statement only makes sense at the very first creation of the linked
list. The very first node in the list has its Next pointer equal to NULL. All
succeeding Next pointers connect to a node in the list. If you were not convinced
before that this linked list behaves like a stack, you should believe it with this
example. Twenty-size letters displayed in reverse order provides ample evidence.
// PROG3904.CPP
// This program creates a linked list with 26 nodes and displays
// the data stored in the linked list.
// The linked list is created as a stack data structure.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
char Data;
ListNode *Next;
};
void main()
{
clrscr();
ListNode *P;
ListNode *Temp;
int K;
Temp = NULL;
PROG3904.CPP OUTPUT
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
So think about this little question. We have a data structure here that we call a
linked list, and this linked list behaves in every way like a stack. So is this data
structure a stack or is the data structure a linked list? Think about it.
Program PROG3905.CPP once again creates a linked list of three nodes. Take a
quick look at the program first on the next page, and the output execution. The
output will probably satisfy you that the program appears to be inclined toward
the queue direction. Why is it now a queue? Maybe these pictures will help.
X Y Z [P] (stack)
The pictures are intentionally drawn so that it appears that the list grows from left
to right. Symbolically speaking, that is correct if you consider that the nodes in
both lists are created starting with the X node and ending with the Z node. In the
case of the stack, the latest or current node that is created, points its Next pointer
to the previous node that was created. Each new node in the stack-type linked list
grows further and further away from the node with the NULL pointer.
The queue-type linked list is a different story. Each new node that is created
assigns NULL to its Next pointer. It seems that the latest node created is
constantly treated like the last node in the list. Furthermore, it is the previous
node that is linked to the current node. The Next pointers are opposite in their
linking scheme. This is precisely what makes one program behave like a stack
and the other program behave like a queue.
// PROG3905.CPP
// This program creates a linked list with three nodes and
// displays the data stored in the linked list.
// The linked list is created as a queue data structure.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
char Data;
ListNode *Next;
};
void main()
{
clrscr();
ListNode *P;
ListNode *Temp;
ListNode *Front;
P = new ListNode;
P->Data = 'Y';
cout << "P->Data: " << P->Data << endl;
P = new ListNode;
P->Data = 'Z';
cout << "P->Data: " << P->Data << endl;
P->Next = NULL;
Temp->Next = P;
Temp = P;
PROG3905.CPP OUTPUT
Front->Data: X
P->Data: Y
P->Data: Z
P->Data: Z
P->Data: Y
P->Data: X
Do you understand why there is an extra pointer used, called Front? The earlier
group of programs seemed to work fine with only two pointers and now there are
three. First of all, you need to realize that it takes two pointers to build any type
of a linked list. One pointer needs to point to each of the two nodes that will be
linked together. The stack data structure implemented with a linked list means
that the “top” of the stack is at the same place as the end of the linked list where
new nodes will be added in the future.
The story is different with a queue. New queue elements are added to the back of
the linked list. This explains why each new node is assigned NULL to its Next
pointer field. The queue builds steadily away from the first node where the list
was started. However, it is the first node that must be accessed when the queue is
traversed.
The importance of the Front pointer is reinforced with the next program. Once
again a loop is used to create a linked list with twenty-six nodes. You will note in
this program that a complete node is created before the loop is started. This very
first node is recorded with the Front pointer and then the loop may start to build
the list for the next twenty-five nodes. This time the alphabet is displayed in the
same order as it was constructed. We are definitely talking queue here.
So are you any closer to the question of what is it? Are these data structures
stacks, or queues or linked lists or everything at the same time? What is going on
here? Keep thinking and remember that the best students do not have the best
answers, they have the best questions.
// PROG3906.CPP
// This program creates a linked list with 26 nodes and displays
// the data stored in the linked list.
// The linked list is created as a queue data structure.
#include <iostream.h>
#include <conio.h>
struct ListNode
{
void main()
{
clrscr();
ListNode *Front;
ListNode *P;
ListNode *Temp;
int K;
PROG3906.CPP OUTPUT
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
You have some serious recollection that linked lists would solve the linear list
problem of shifting elements during insertion and deletion processes. So far none
of this has been addressed. The two previous linked list structures have behaved
like a stack and a queue and that basically means that all access has been at one
end of the list. There has not been any need to insert a node somewhere in the
middle of the list. This should be odd because that was one of the big
motivations of working with link lists.
The reason for starting with a stack and a queue was to take small bites at a time
of this linked list stuff. The stack is the easiest linked list to build and the queue a
little bit more complicated. Now you are ready to treat a linked list properly and
make sure that the list is ordered in the manner of a linear list. The list should be
created such that the data is sorted by some pre-determined method.
The next program example starts by filling an array with a random set of
numbers. This array is then passed to another function in charge of creating an
ordered linked list. The process - logically speaking - is completely identical to
the insertion sort that you learned long ago. You need to find the proper location
for the new number and insert the number at that location in the list. This process
is simpler to implement with an indexed list because every element in the array
can be accessed with its index. Sorting with an array becomes a manipulation and
shifting process based on the index values of adjacent list elements.
The same process with a linked list is more efficient but also more complex. It is
not sufficient to identify the insert or delete location. A single pointer at a desired
location is not capable of handling the insertion process.
Consider the following diagram. An ordered linked list exists with data ordered
alphabetically. A new node needs to be inserted with data K.
[P] K
[F] A G M T
[P]
[F] A G M T
[T1] [T2]
Provided we have pointers positioned, as shown above, the linking of the new
node can be accomplished with the following two statements:
T1->Next = P;
P->Next = T2;
After these two statements are executed the linked list takes on the following
appearance. Node K is now inserted into the correct location.
A G M T
A G K M T
// PROG3907.CPP
// This program creates an ordered linked list of integers.
// Each element of a random integer array is inserted in the
// list at the correct location. This program also shows how
// to use a user-defined pointer type.
// This program becomes an insertion sort implemented with a
// dynamic linked list data structure.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include "APVECTOR.H"
struct ListNode
{
int Info;
ListNode* Next;
};
void main()
{
ArrayType List;
ListPtr Front;
CreateList(List);
SortList(List,Front);
DisplayList(Front);
}
void DisplayList(ListPtr P)
// This function displays the data in the linked list created
// by the SortList function.
{
cout << endl;
while (P != NULL)
{
cout << P->Info << " ";
P = P->Next;
}
getch();
}
PROG3907.CPP OUTPUT
1095 1035 4016 1299 4201 2954 5832 2761 7302 9549
1035 1095 1299 2761 2954 4016 4201 5832 7302 9549
The previous section created an ordered linked list. The primary tool used to
create the list was a set of temporary pointers, placed properly in the existing list,
to facilitate inserting each new node. In this section we will look at an existing
ordered linked list and delete specified nodes from the list.
In the next program example a simple, artificial list is created. Using a series of
ordered integers, the linked list becomes automatically ordered with less code
involved. This program needs to concentrate on deletion, not on insertion.
[T1] [T2]
A G K M T
[T1] [T2]
A G K M T
After the links are reconnected and the unwanted node is no longer part of the
list, some process removes the node completely. The result is the next picture
with a clean list and the K node is nowhere to be seen.
A G M T
It is easy to argue that the deletion process does not require two temporary
pointers. The single pointer attached to the node, immediately before the target
node, will effectively take the target node out off the linked list. This is true, but
a pointer needs to be attached to the target node so that it can be properly deleted
and its memory space returned to the heap.
// PROG3908.CPP
// This program demonstrates how to delete an element from an
// ordered linked list. The ordered linked list is artificially
// created to simplify the program.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
struct ListNode
{
int Info;
ListNode* Next;
void main()
{
ListPtr Front;
CreateList(Front);
DisplayList(Front);
DeleteNode(Front);
DisplayList(Front);
}
void DisplayList(ListPtr P)
{
cout << endl << endl;
while (P != NULL)
{
cout << P->Info << " ";
P = P->Next;
}
getch();
}
We will not be quickly satisfied with this program by executing one quick sample
to check for accuracy. With this program let us thoroughly investigate to see
what happens in a variety of different cases.
PROG3908.CPP OUTPUT #1
100 200 300 400 500 600 700 800 900 1000
Output #1 deletes an existing node from the middle of the ordered list. The
program works correctly, as expected, and target node (500) is removed.
PROG3908.CPP OUTPUT #2
100 200 300 400 500 600 700 800 900 1000
Output #2 deletes an existing node from the end of the ordered list. The program
works correctly, as expected, and target node (1000) is removed.
PROG3908.CPP OUTPUT #3
100 200 300 400 500 600 700 800 900 1000
100 200 300 400 500 600 700 800 900 1000
Output #3 deletes an existing node from the front of the ordered list. The
program does not work as expected. The target node (100) is not removed from
the list.
PROG3908.CPP OUTPUT #4
100
100
You may wonder why a program is presented that appears to have various flaws
in it. The program appears to delete target nodes ... part of the time. This is not
exactly the type of program that students should be studying as a good case study
to be followed. However, an important point is made here. Many programs are
flawed because programmers fail to consider all the possible cases involved.
This section is aimed to prevent the problems mentioned with the previous
section. Essentially, we will look once again at an ordered linked list, both from
the insertion and deletion point of view. However, we now wish to be very
thorough and consider all the possible cases. So starting with insertion, what
possible situation might arise?
A list of cases follows below. Would you have thought of all these possibilities?
Do you find that perhaps some cases have been left out? After all, who said that
the author of this stuff is without mistakes. Let’s face it, you guys are now in
chapter 39, and if you have not noticed that I make mistakes by now, you have
not been reading very carefully.
Check out program PROG3909.CPP and see if all the cases above are taking
into consideration. A good start is to test the program such that each case will be
considered and then check carefully if the test yields the expected results.
Students are so frequently excited with a solution, both on paper and on the
computer, that they do not stop to check the solution thoroughly.
Time and again I have seen students satisfied with the correct output of a single
testing case. Curb your enthusiasm for completion until after you have tested the
program execution very thoroughly with a wide selection of test data.
// PROG3909.CPP
// This program demonstrates inserting into an ordered
// linked list with consideration of all possible cases.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
struct ListNode
{
int Info;
ListNode* Next;
};
void DisplayList(ListPtr P)
// This function displays the list
{
cout << endl << endl;
while (P != NULL)
{
cout << P->Info << " ";
P = P->Next;
}
getch();
}
PROG3909.CPP OUTPUT #1
Output #1 inserts a new node in the middle of an existing list. The program
works as expected. The new node (350) is inserted properly.
Output #2 inserts a new node in the front of an existing list. The program works
as expected. The new node (50) is inserted properly.
PROG3909.CPP OUTPUT #3
Output #3 inserts a new node at the end of an existing list. The program works as
expected. The new node (700) is inserted properly.
PROG3909.CPP OUTPUT #4
100
We now move on and investigate the deletion process. Are the number of
different cases the same as they were for insertion? Are there more or less? Look
at the list below and see if you agree?
You can see that the deletion cases are not exactly the same as the insertion cases.
One major difference is that it is always possible to insert a new node, assuming
that memory space is available. On the other hand, deletion is only possible if the
target node exists in a given list. Look at program PROG3909.CPP, on the next
page, and see if all the cases are covered.
// PROG3910.CPP
// This program demonstrates deleting from an ordered
// linked list with consideration of all possible cases.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include "BOOL.H"
struct ListNode
{
int Info;
ListNode* Next;
};
void main()
{
ListPtr Front;
CreateList(Front);
DisplayList(Front);
DeleteNode(Front);
DisplayList(Front);
}
{
P = new ListNode;
P->Info = 100;
P->Next = NULL;
Temp = P;
F = P;
for (K = 2; K <= N; K++)
{
P = new ListNode;
P->Info = K * 100;
P->Next = NULL;
Temp->Next = P;
PROG3910.CPP OUTPUT #1
Output #1 tries to delete a target node from an existing list. The program works
as expected. The target node (350) does not exist in the list and a message
indicates that the node was not found.
PROG3910.CPP OUTPUT #2
Output #2 deletes a node from the middle of an existing list. The program works
as expected. The target node (300) is deleted properly.
Output #3 deletes a node from the front of an existing list. The program works as
expected. The target node (100) is deleted properly.
PROG3910.CPP OUTPUT #4
Output #4 deletes a node from the end of an existing list. The program works as
expected. The target node (600) is deleted properly.
PROG3910.CPP OUTPUT #5
Output #5 tries to delete a target node from a non-existing list. The program
works as expected. The target node (100) does not exist in the list and a message
indicates that the node was not found.
Consider the linked list diagram below. It is a lovely list with five nodes. Each
node has one field for character data and a second field to store the pointer to the
next node in the list. F point to the first node in the linked list, which is ordered
alphabetically.
[F] A G K M T
Now all this linked list stuff and diagrams with nodes and pointers is terrific, but
hopefully you do not expect to look inside the computer and find a bunch of
pointers that link different memory locations together. At least you should not
expect any type of arrow-shaped pointers. You have worked with pointers
before. A pointer stores a memory address. So let’s get a little more technical
and represent the linked list in a manner that resembles reality more closely.
The diagram, shown later, represents memory cells. Each cell is identified by a
base-16 memory address like @7b00. The @ indicates address in this
illustration. Each memory cell is four bytes. Two bytes are for the integer data
field and another two bytes are for the pointer data field. Keep in mind that not
every compiler allocates memory in the exact same manner. The importance here
is to visualize a memory grid of addresses drawn such that every cell can hold the
information of one node in the linked list. Now also keep in mind that there is
one pointers, F the Front pointer, which needs to be stored somewhere.
A pointer may store a memory address, but this memory address in turn needs to
be stored somewhere. The space requirement for the front pointer is technically
only two bytes. The illustration, on the next page, may give the impression that
four bytes are needed which is not true.
The linked list diagram, with its arrow-style pointers, is drawn again above the
memory segment diagram. This allows a clear comparison between the two types
of linked list representations.
@7b44 M
@7b94
@7b30 @7b34 @7b38 @7b3c @7b40 @7b44 @7b48 @7b4c
G A
@7b68 @7b30
@7b60 @7b64 @7b68 @7b6c @7b70 @7b74 @7b78 @7b7c
K
@7b1c
T
@0000
Let us step through this diagram and see if you can visualize the linked list that is
represented here. It is possible that many of you have little trouble with the
visualization because you look at the diagram at the top of the page.
The exercises that follow will look quite different than any previous multiple
choice questions. For each question you will be provided with a diagram that
illustrates a linked list at the start of the question. A number of program
statements follow that alters the storage in the linked list. Your job is then to
determine which one of the diagrams that follow represents the new linked list.
This style of question was developed to encourage students to visualize the linked
lists that they use. You will also find a number of questions on this style on the
APCS Examination.
The answers of these exercises will not be explained. However, at the end of the
section the answers are provided so you can check your logic. Draw pictures of
the different stages of the linked list. Be especially careful not to be off by one
node. There is quite a difference between the following two statements:
while(P != NULL)
while(P->Next != NULL)
Please be aware that various exercises are designed to test your ability to interpret
the syntax and logic of linked lists implementations. Some examples may use
statements that should not be used in real programs.
struct ListNode
{
char Data;
ListNode * Next;
};
ListNode *P1, *P2, *P3;
In the exercises that follow you will be shown some initial list configuration. Do
not be concerned how this list was developed. Look at the list and then consider
the program statements that follow. At the conclusion of executing the provided
program statements you need to select the diagram that represents the new
configuration of the linked list. Note that only the list configuration with linking
pointers is shown after the program segment has finished execution. Any of the P
pointers are intentionally not illustrated to make the diagrams less cluttered.
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
P1-Data = P2->Data;
(A) A B C D
(B) A B C E
(C) E B C D
(D) E E E E
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
while (P1->Next != NULL)
P1 = P1->Next;
P1->Data = P2->Data;
(A) A B C D
(B) A E C D
(C) A B C E
(D) A B E D
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
while (P1->Next->Next != NULL)
P1 = P1->Next;
P1->Data = P2->Data;
(A) A B C D
(B) A E C D
(C) A B C E
(D) A B E D
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
while (P1->Next->Next->Next != NULL)
P1 = P1->Next;
P2->Data = P1->Data;
(A) A B C D
(B) A E C D
(C) A B C E
(D) A B E D
[P1]
A B C D
How is the linked list represented after the program segment below executes?
(A) A B C D
(B) D C B A
(C) D D D D
(D) A A A A
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = P1->Next->Next->Data;
while (P1->Next != NULL)
{
P1 = P1->Next;
P1->Data = P2->Data;
}
(A) A B C D
(B) C C C C
(C) A B C C
(D) C C C D
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
P2->Next = NULL;
while (P1->Next != NULL)
P1 = P1->Next;
P1->Next = P2;
(A) A B C D E
(B) A B C E D
(C) A B C E
(D) A B D C
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
while (P1->Next->Next != NULL)
{
P2 = P1;
P1 = P1->Next;
P2->Data = P1->Data;
}
(A) A B C D E
(B) B C D E A
(C) B C D D
(D) B C D E
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P2 = new ListNode;
P2->Data = 'E';
P2->Next = NULL;
while (P1->Data != 'C')
{
P3 = P1;
P1 = P1->Next;
}
P3->Next = P2;
P2->Next = P1;
(A) A B C E D
(B) A B E C D
(C) A E B C D
(D) A B C D E
[P1]
A B C D
How is the linked list represented after the program segment below executes?
P3 = new ListNode;
while (P1->Next != NULL)
{
P2 = P1;
P1 = P1->Next;
P3->Data = P1->Data;
P1->Data = P2->Data;
P2->Data = P3->Data;
}
(A) A B C D
(B) A B C E
(C) B C D A