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.
A simple polygon P is said to be an LR-visibility polygon if there exists two points s and t on the boundary of P such that every point of the clockwise boundary of P from s to t (denoted as L) is visible from some point of the counterclockwise boundary of P from s to t (denoted as R) and vice versa (see Figure 4.1(a)). LR-visibility polygons can be viewed as a generalization of weak visibility polygons (discussed in Chapter 3). We know that a simple polygon P is a weak visibility polygon from a chord if there exists two points s and t on bd(P) such that (i) s and t are mutually visible, and (ii) every point of the clockwise boundary from s to t is visible from some point of the counterclockwise boundary from s to t and vice versa. If the condition (i) is removed, then it defines LR-visibility polygons, which contains weak visibility polygons as a subclass. It can be seen that if a point moves along any path between s and t inside an LR-visibility polygon, it can see the entire polygon. LR-visibility polygons are also called streets and this class of polygons was first considered while studying the problem of walking in a polygon. For more details, see Icking and Klein [200] and Klein [219].
Assume that a point-robot moves in straight-line paths inside a polygonal region P. Every time it has to change its direction of the path, it stops and rotates until it directs itself to the new direction. In the process, it makes several turns before reaching its destination. If straight line motions are ‘cheap’ but rotations are ‘expensive’, minimizing the number of turns reduces the cost of the motion although it may increase the length of the path. This motivates the study of link paths inside a polygonal region P. For more details on applications of such paths, see the review article of Maheshwari et al. [253].
A link path between two points s and t of a polygon P (with or without holes) is a path inside P that connects s and t by a chain of line segments (called links). A minimum link path between s and t is a link path connecting s and t that has the minimum number of links (see Figure 7.1). Observe that there may be several link paths between s and t with the minimum number of links. The link distance between any two points of P is the number of links in the minimum link path between them.
The problem of computing the minimum link path between any two points inside a simple polygon were first studied by ElGindy [126] and Suri [318].
The notion of weak visibility of a polygon from a segment was introduced by Avis and Toussaint [42] in the context of the art gallery problem. They considered a variation of the problem when there is only one guard and the guard is permitted to move along an edge of the polygon. They defined visibility from an edge vivi+1 in a simple polygon P in three different ways.
P is said to be completely visible from viυi+1 if every point z ∈ P and any point w ∈ vivi+1, w and z are visible (Figure 3.1(a)).
P is said to be strongly visible from vivi+1 if there exists a point w ∈ vivi+1 such that for every point z ∈ P, w and z are visible (Figure 3.1(b)).
P is said to be weakly visible from vivi+1 if each point z ∈ P, there exists a point w ∈ vivi+1 (depending on z) such that w and z are visible (Figure 3.1(c)).
If P is completely visible from vivi+1, the guard can be positioned at any point w on vivi+1. In other words, P and the visibility polygon V(w) of P from any point w ∈ vivi+1 are same. If P is strongly visible from vivi+1, there exists at least one point w on vivi+1 from which the guard can see the entire P, i.e., P = V(w). Finally, if P is weakly visible from vivi+1, it is necessary for the guard to patrol along vivi+1 in order to see the entire P.
The visibility graph is a fundamental structure in computational geometry; some early applications of visibility graphs include computing Euclidean shortest paths in the presence of obstacles [249] and in decomposing two-dimensional shapes into clusters [306]. The visibility graph (also called the vertex visibility graph) of a polygon P with or without holes is the undirected graph of the visibility relation on the vertices of P. The visibility graph of P has a node for every vertex of P and an edge for every pair of visible vertices in P. Figure 5.1(b) shows the visibility graph of the polygon in Figure 5.1(a). We sometimes draw the visibility graph directly on the polygon, as shown in Figure 5.1(c). It can be seen that every triangulation of P corresponds to a sub-graph of the visibility graph of P. The visibility graph of a line segment arrangement is defined similarly, where the endpoints of the line segments are represented as the nodes of the visibility graph.
Consider the problem of computing the visibility graph of a polygon P (with or without holes) having a total of n vertices. The visible pairs of vertices in P can be computed by checking intersections of segments connecting pairs of vertices in P with each polygonal edge of P. This naive method takes O(n3) time as in the first algorithm for computing the visibility graph given by Lozano-Perez and Wesley [249].
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].
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.