To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
In the previous chapter we discussed how to compute the visibility graph of a polygon P with or without holes. Consider the opposite problem: let G be a given graph. The problem is to determine whether there is a polygon P whose visibility graph is the given graph G. This problem is called the visibility graph recognition problem. The problem of actually drawing one such polygon P is called the visibility graph reconstruction problem. The visibility graph recognition and reconstruction problems are long-standing open problems. So far, only partial results have been achieved. It has been shown by Everett [133] that visibility graph reconstruction is in PSPACE. This is the only upper bound known on the complexity of either problem.
Ghosh [154] presented three necessary conditions in 1986 for recognizing visibility graphs of simple polygons under the assumption that a Hamiltonian cycle of the given graph, which corresponds to the boundary of the simple polygon, is given as input along with the graph. It has been pointed out by Everett and Corneil [133, 135] that these conditions are not sufficient as there are graphs that satisfy the three necessary conditions but they are not visibility graphs of any simple polygon. These counter-examples can be eliminated once the third necessary condition is strengthened.
Determining the visible region of a geometric object from a given source under various constraints is a well-studied problem in computational geometry [30]. The visibility polygon V(q) of a point q in a simple polygon P is the set of all points of P that are visible from q. In other words, V(q) = {p ∈ P|q sees p}. A similar definition holds in a polygon with holes or an arrangement of segments. The problem of computing the visibility polygon V(q) of a point q is related to hidden line elimination problem and it is a part of the rendering process in computer graphics [115]. Figure 2.1 shows V(q) in a simple polygon, a polygon with holes, and a line segment arrangement. By definition, any V(q) is a star-shaped polygon and q belongs to the kernel of P. The visibility polygon of a point in a line segment arrangement may not be always bounded.
Let ab be an edge on the boundary of V(q) such that (i) no point of ab, except the points a and b, belong to the boundary of P, (ii) three points q, a and b are collinear, and (iii) a or b is a vertex of P. Such an edge ab is called a constructed edge of V(q).
Let q1, q2, …, qm be a set of internal points of a polygon P with holes with a total of n vertices. Consider the problem of computing visibility polygons of points q1, q2, …, qm in the polygon P. Since the visibility polygon of P from each point qi can be computed in O(n log n) time by the algorithm of Asano [27] (see Section 2.3), the problem can be solved in O(mn log n) time. Suppose m is quite large compared to n. In that case, it may be a good idea to construct data structures by processing P once so that the visibility polygon from each query point qi can be computed in less than O(n log n) time with the help of these data structures. In fact, it has been shown by Asano et al. [28] that after spending O(n2) time in preprocessing of P, the visibility polygon from each query point qi can be computed in O(n) time. Thus the overall time complexity for solving this problem is reduced from O(mn log n) to O(mn). Such problems, that require a large number of computations of similar type on the same polygonal domain, are known as query problems in computational geometry [291].
This book by Felipe Cucker and Ding-Xuan Zhou provides solid mathematical foundations and new insights into the subject called learning theory.
Some years ago, Felipe and I were trying to find something about brain science and artificial intelligence starting from literature on neural nets. It was in this setting that we encountered the beautiful ideas and fast algorithms of learning theory. Eventually we were motivated to write on the mathematical foundations of this new area of science.
I have found this arena to with its new challenges and growing number of application, be exciting. For example, the unification of dynamical systems and learning theory is a major problem.Another problem is to develop a comparative study of the useful algorithms currently available and to give unity to these algorithms. How can one talk about the “best algorithm” or find the most appropriate algorithm for a particular task when there are so many desirable features, with their associated trade-offs? How can one see the working of aspects of the human brain and machine vision in the same framework?
I know both authors well. I visited Felipe in Barcelona more than 13 years ago for several months, and when I took a position in Hong Kong in 1995, I asked him to join me. There Lenore Blum, Mike Shub, Felipe, and I finished a book on real computation and complexity. I returned to the USA in 2001, but Felipe continues his job at the City University of Hong Kong. Despite the distance we have continued to write papers together. I came to know Ding-Xuan as a colleague in the math department at City University. We have written…
Visibility is a natural phenomenon in everyday life. We see objects around us and then decide our movement accordingly. Seeing an object means identifying the portions of the object visible from the current position of an observer. The entire object may not be visible as some of its parts may be hidden from the observer. The observer also determines shapes and sizes of visible portions of an object. Visible portions of an object change as the observer moves from one position to another. Moreover, the observer may see several objects in different directions from its current position; the visible portions of these objects form the scene around the observer. Constructing such a scene continuously is very natural for a human observer as the human visual system can execute such tasks effortlessly.
Suppose a robot wants to move from a starting position to a target position without colliding with any object or obstacle around it. The robot constructs the scene around itself from its current position and then guides its motion in the free space lying between itself and the visible portion of the objects around it. The positions of the robot and the objects can be represented in the computer of the robot by their x, y and z co-ordinates and therefore, the scene consisting of visible portions of these objects can be computed for the current position of the robot.
Strings are common to most computer programs. Certain types of programs, such as word processors and web applications, make heavy use of strings, which forces the programmer of such applications to pay special attention to the efficiency of string processing. In this chapter, we examine how C# works with strings, how to use the String class, and finally, how to work with the StringBuilder class. The StringBuilder class is used when a program must make many changes to a String object because strings and String objects are immutable, whereas StringBuilder objects are mutable. We'll explain all this later in the chapter.
WORKING WITH THE STRING CLASS
A string is a series of characters that can include letters, numbers, and other symbols. String literals are created in C# by enclosing a series of characters within a set of double quotation marks. Here are some examples of string literals:
“David Ruff”
“the quick brown fox jumped over the lazy dog”
“123-45-6789”
“mmcmillan@pulaskitech.edu”
A string can consist of any character that is part of the Unicode character set. A string can also consist of no characters. This is a special string called the empty string and it is shown by placing two double quotation marks next to each other (“ ”). Please keep in mind that this is not the string that represents a space. That string looks like this—“ ”.
The study of networks has become one of the great scientific hotbeds of this new century, though mathematicians and others have been studying networks for many hundreds of years. Recent developments in computer technology (i.e., the Internet), and in social theory (the social network, popularly conceived in the concept of “six degrees of separation”), have put a spotlight on the study of networks.
In this chapter, we look at how networks are modeled with graphs. We're not talking about the graphs such as pie graphs or bar graphs. We define what a graph is, how they're represented in VB.NET, and how to implement important graph algorithms. We also discuss the importance of picking the correct data representation when working with graphs, since the efficiency of graph algorithms is dependent on the data structure used.
GRAPH DEFINITIONS
A graph consists of a set of vertices and a set of edges. Think of a map of your state. Each town is connected with other towns via some type of road. A map is a type of graph. Each town is a vertex and a road that connects two towns is an edge. Edges are specified as a pair, (v1, v2), where v1 and v2 are two vertices in the graph. A vertex can also have a weight, sometimes also called a cost.
A dictionary is a data structure that stores data as a key–value pair. The DictionaryBase class is used as an abstract class to implement different data structures that all store data as key–value pairs. These data structures can be hash tables, linked lists, or some other data structure type. In this chapter, we examine how to create basic dictionaries and how to use the inherited methods of the DictionaryBase class. We will use these techniques later when we explore more specialized data structures.
One example of a dictionary-based data structure is the SortedList. This class stores key–value pairs in sorted order based on the key. It is an interesting data structure because you can also access the values stored in the structure by referring to the value's index position in the data structure, which makes the structure behave somewhat like an array. We examine the behavior of the SortedList class at the end of the chapter.
THE DICTIONARYBASE CLASS
You can think of a dictionary data structure as a computerized word dictionary. The word you are looking up is the key, and the definition of the word is the value. The DictionaryBase class is an abstract (MustInherit) class that is used as a basis for specialized dictionary implementations.
Trees are a very common data structure in computer science. A tree is a nonlinear data structure that is used to store data in a hierarchical manner. We examine one primary tree structure in this chapter, the binary tree, along with one implementation of the binary tree, the binary search tree. Binary trees are often chosen over more fundamental structures, such as arrays and linked lists, because you can search a binary tree quickly (as opposed to a linked list) and you can quickly insert data and delete data from a binary tree (as opposed to an array).
THE DEFINITION OF A TREE
Before we examine the structure and behavior of the binary tree, we need to define what we mean by a tree. A tree is a set of nodes connected by edges. An example of a tree is a company's organization chart (see Figure 12.1).
The purpose of an organization chart is to communicate to the viewer the structure of the organization. In Figure 12.1, each box is a node and the lines connecting the boxes are the edges. The nodes, obviously, represent the entities (people) that make up an organization. The edges represent the relationship between the entities. For example, the Chief Information Officer (CIO), reports directly to the CEO, so there is an edge between these two nodes. The IT manager reports to the CIO so there is an edge connecting them.
The study of data structures and algorithms is critical to the development of the professional programmer. There are many, many books written on data structures and algorithms, but these books are usually written as college textbooks and are written using the programming languages typically taught in college—Java or C++. C# is becoming a very popular language and this book provides the C# programmer with the opportunity to study fundamental data structures and algorithms.
C# exists in a very rich development environment called the .NET Framework. Included in the .NET Framework library is a set of data structure classes (also called collection classes), which range from the Array, ArrayList, and Collection classes to the Stack and Queue classes and to the HashTable and the SortedList classes. The data structures and algorithms student can now see how to use a data structure before learning how to implement it. Previously, an instructor had to discuss the concept of, say, a stack, abstractly until the complete data structure was constructed. Instructors can now show students how to use a stack to perform some computation, such as number base conversions, demonstrating the utility of the data structure immediately. With this background, the student can then go back and learn the fundamentals of the data structure (or algorithm) and even build their own implementation.
In this chapter, we examine algorithms for sorting data that are more complex than the algorithms examined in Chapter 4. These algorithms are also more efficient, and one of them, the QuickSort algorithm, is generally considered to be the most efficient sort to use in most situations. The other sorting algorithms we'll examine are the ShellSort, the MergeSort, and the HeapSort.
To compare these advanced sorting algorithms, we'll first discuss how each of them is implemented, and in the exercises you will use the Timing class to determine the efficiency of these algorithms.
THE SHELLSORT ALGORITHM
The ShellSort algorithm is named after its inventor Donald Shell. This algorithm is fundamentally an improvement of the insertion sort. The key concept in this algorithm is that it compares items that are distant rather than adjacent items, as is done in the insertion sort. As the algorithm loops through the data set, the distance between each item decreases until at the end the algorithm is comparing items that are adjacent.
ShellSort sorts distant elements by using an increment sequence. The sequence must start with 1, but can then be incremented by any amount.
Searching for data is a fundamental computer programming task and one that has been studied for many years. This chapter looks at just one aspect of the search problem—searching for a given value in a list (array).
There are two fundamental ways to search for data in a list: the sequential search and the binary search. Sequential search is used when the items in the list are in random order; binary search is used when the items are sorted in the list.
SEQUENTIAL SEARCHING
The most obvious type of search is to begin at the beginning of a set of records and move through each record until you find the record you are looking for or you come to the end of the records. This is called a sequential search.
A sequential search (also called a linear search) is very easy to implement. Start at the beginning of the array and compare each accessed array element to the value you're searching for. If you find a match, the search is over. If you get to the end of the array without generating a match, then the value is not in the array.
Whereas the String and StringBuilder classes provide a set of methods that can be used to process string-based data, the RegEx and its supporting classes provide much more power for string-processing tasks. String processing mostly involves looking for patterns in strings (pattern matching) and it is performed via a special language called a regular expression. In this chapter, we look at how to form regular expressions and how to use them to solve common text processing tasks.
AN INTRODUCTION TO REGULAR EXPRESSIONS
A regular expression is a language that describes patterns of characters in strings, along with descriptors for repeating characters, alternatives, and groupings of characters. Regular expressions can be used to perform both searches in strings and substitutions in strings.
A regular expression itself is just a string of characters that define a pattern you want to search for in another string. Generally, the characters in a regular expression match themselves, so that the regular expression “the” matches that sequence of characters wherever they are found in a string.
A regular expression can also include special characters that are called metacharacters. Metacharacters are used to signify repetition, alternation, or grouping. We will examine how these metacharacters are used shortly.
Most experienced computer users have used regular expressions in their work, even if they weren't aware they were doing so at the time.