没有合适的资源?快使用搜索试试~ 我知道了~
首页Linked List Problems 链表 习题
资源详情
资源评论
资源推荐

Linked List
Problems
By Nick Parlante Copyright ©1998-2002, Nick Parlante
Abstract
This document reviews basic linked list code techniques and then works through 18
linked list problems covering a wide range of difficulty. Most obviously, these problems
are a way to learn about linked lists. More importantly, these problems are a way to
develop your ability with complex pointer algorithms. Even though modern languages
and tools have made linked lists pretty unimportant for day-to-day programming, the
skills for complex pointer algorithms are very important, and linked lists are an excellent
way to develop those skills.
The problems use the C language syntax, so they require a basic understanding of C and
its pointer syntax. The emphasis is on the important concepts of pointer manipulation and
linked list algorithms rather than the features of the C language.
For some of the problems we present multiple solutions, such as iteration vs. recursion,
dummy node vs. local reference. The specific problems are, in rough order of difficulty:
Count, GetNth, DeleteList, Pop, InsertNth, SortedInsert, InsertSort, Append,
FrontBackSplit, RemoveDuplicates, MoveNode, AlternatingSplit, ShuffleMerge,
SortedMerge, SortedIntersect, Reverse, and RecursiveReverse.
Contents
Section 1 — Review of basic linked list code techniques 3
Section 2 — 18 list problems in increasing order of difficulty 10
Section 3 — Solutions to all the problems 20
This is document #105, Linked List Problems, in the Stanford CS Education Library.
This and other free educational materials are available at http://cslibrary.stanford.edu/.
This document is free to be used, reproduced, or sold so long as this notice is clearly
reproduced at its beginning.
Related CS Education Library Documents
Related Stanford CS Education library documents...
• Linked List Basics (http://cslibrary.stanford.edu/103/)
Explains all the basic issues and techniques for building linked lists.
• Pointers and Memory (http://cslibrary.stanford.edu/102/)
Explains how pointers and memory work in C and other languages. Starts
with the very basics, and extends through advanced topics such as
reference parameters and heap management.
• Binary Trees (http://cslibrary.stanford.edu/110/)
Introduction to binary trees
• Essential C (http://cslibrary.stanford.edu/101/)
Explains the basic features of the C programming language.

2
• The Great Tree List Problem (http://cslibrary.stanford.edu/109/)
Presents the greatest recursive pointer problem ever devised.
Why Linked Lists Are Great To Study
Linked lists hold a special place in the hearts of many programmers. Linked lists are great
to study because...
• Nice Domain The linked list structure itself is simple. Many linked list
operations such as "reverse a list" or "delete a list" are easy to describe and
understand since they build on the simple purpose and structure of the
linked list itself.
• Complex Algorithm Even though linked lists are simple, the algorithms
that operate on them can be as complex and beautiful as you want (See
problem #18). It's easy to find linked list algorithms that are complex, and
pointer intensive.
• Pointer Intensive Linked list problems are really about pointers. The
linked list structure itself is obviously pointer intensive. Furthermore,
linked list algorithms often break and re-weave the pointers in a linked list
as they go. Linked lists really test your understanding of pointers.
• Visualization Visualization is an important skill in programming and
design. Ideally, a programmer can visualize the state of memory to help
think through the solution. Even the most abstract languages such as Java
and Perl have layered, reference based data structures that require
visualization. Linked lists have a natural visual structure for practicing this
sort of thinking. It's easy to draw the state of a linked list and use that
drawing to think through the code.
Not to appeal to your mercenary side, but for all of the above reasons, linked list
problems are often used as interview and exam questions. They are short to state, and
have complex, pointer intensive solutions. No one really cares if you can build linked
lists, but they do want to see if you have programming agility for complex algorithms and
pointer manipulation. Linked lists are the perfect source of such problems.
How To Use This Document
Try not to use these problems passively. Take some time to try to solveeach problem.
Even if you do not succeed, you will think through the right issues in the attempt, and
looking at the given solution will make more sense. Use drawings to think about the
problems and work through the solutions. Linked lists are well-suited for memory
drawings, so these problems are an excellent opportunity to develop your visualization
skill. The problems in this document use regular linked lists, without simplifcations like
dummy headers.
Dedication
This Jan-2002 revision includes many small edits. The first major release was Jan 17,
1999. Thanks to Negar Shamma for her many corrections. This document is distributed
for the benefit and education of all. Thanks to the support of Eric Roberts and Stanford
University. That someone seeking education should have the opportunity to find it. May
you learn from it in the spirit of goodwill in which it is given.
Best Regards, Nick Parlante -- nick.parlante@cs.stanford.edu

3
Section 1 —
Linked List Review
This section is a quick review of the concepts used in these linked list problems. For more
detailed coverage, see Link List Basics (http://cslibrary.stanford.edu/103/) where all of
this material is explained in much more detail.
Linked List Ground Rules
All of the linked list code in this document uses the "classic" singly linked list structure:
A single head pointer points to the first node in the list. Each node contains a single
.next pointer to the next node. The .next pointer of the last node is NULL. The
empty list is represented by a NULL head pointer. All of the nodes are allocated in the
heap.
For a few of the problems, the solutions present the temporary "dummy node" variation
(see below), but most of the code deals with linked lists in their plain form. In the text,
brackets {} are used to describe lists — the list containing the numbers 1, 2, and 3 is
written as {1, 2, 3}. The node type used is...
struct node {
int data;
struct node* next;
};
To keep thing ssimple, we will not introduce any intermediate typedefs. All pointers to
nodes are declared simply as struct node*. Pointers to pointers to nodes are declared
as struct node**. Such pointers to pointers are often called "reference pointers".
Basic Utility Functions
In a few places, the text assumes the existence of the following basic utility functions...
• int Length(struct node* head);
Returns the number of nodes in the list.
• struct node* BuildOneTwoThree();
Allocates and returns the list {1, 2, 3}. Used by some of the example code
to build lists to work on.
• void Push(struct node** headRef, int newData);
Given an int and a reference to the head pointer (i.e. a struct
node** pointer to the head pointer), add a new node at the head of the
list with the standard 3-step-link-in: create the new node, set its .next to
point to the current head, and finally change the head to point to the new
node. (If you are not sure of how this function works, the first few
problems may be helpful warm-ups.)

4
Use of the Basic Utility Functions
This sample code demonstrates the basic utility functions being used. Their
implementations are also given in the appendix at the end of the document.
void BasicsCaller() {
struct node* head;
int len;
head = BuildOneTwoThree(); // Start with {1, 2, 3}
Push(&head, 13); // Push 13 on the front, yielding {13, 1, 2, 3}
// (The '&' is because head is passed
// as a reference pointer.)
Push(&(head->next), 42); // Push 42 into the second position
// yielding {13, 42, 1, 2, 3}
// Demonstrates a use of '&' on
// the .next field of a node.
// (See technique #2 below.)
len = Length(head); // Computes that the length is 5.
}
If these basic functions do not make sense to you, you can (a) go see Linked List Basics
(http://cslibrary.stanford.edu/103/) which explains the basics of linked lists in detail, or
(b) do the first few problems, but avoid the intermediate and advanced ones.
Linked List Code Techniques
The following list presents the most common techniques you may want to use in solving
the linked list problems. The first few are basic. The last few are only necessary for the
more advanced problems.
1. Iterate Down a List
A very frequent technique in linked list code is to iterate a pointer over all the nodes in a
list. Traditionally, this is written as a while loop. The head pointer is copied into a local
variable current which then iterates down the list. Test for the end of the list with
current!=NULL. Advance the pointer with current=current->next.
// Return the number of nodes in a list (while-loop version)
int Length(struct node* head) {
int count = 0;
struct node* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return(count);
}
Alternately, some people prefer to write the loop as a for which makes the initialization,
test, and pointer advance more centralized, and so harder to omit...
for (current = head; current != NULL; current = current->next) {

5
2. Changing a Pointer Using a Reference Pointer
Many list functions need to change the caller's head pointer. In C++, you can just declare
the pointer parameter as an & argument, and the compiler takes care of the details. To do
this in the C language, pass a pointer to the head pointer. Such a pointer to a pointer is
sometimes called a "reference pointer". The main steps for this technique are...
• Design the function to take a pointer to the head pointer. This is the
standard technique in C — pass a pointer to the "value of interest" that
needs to be changed. To change a struct node*, pass a struct
node**.
• Use '&' in the caller to compute and pass a pointer to the value of interest.
• Use '*' on the parameter in the callee function to access and change the
value of interest.
The following simple function sets a head pointer to NULL by using a reference
parameter....
// Change the passed in head pointer to be NULL
// Uses a reference pointer to access the caller's memory
void ChangeToNull(struct node** headRef) { // Takes a pointer to
// the value of interest
*headRef = NULL; // use '*' to access the value of interest
}
void ChangeCaller() {
struct node* head1;
struct node* head2;
ChangeToNull(&head1); // use '&' to compute and pass a pointer to
ChangeToNull(&head2); // the value of interest
// head1 and head2 are NULL at this point
}
Here is a drawing showing how the headRef pointer in ChangeToNull() points back to
the variable in the caller...
Stack
head1
headRef
ChangeToNull(&head1)
ChangeCaller()
剩余34页未读,继续阅读


















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0