Data Structures and Algorithms using Python
Copyright © 2023 by Rance Necaise
Table Of Contents
Data Structures and Algorithms using Python
Copyright © 2023
by Rance Necaise

2.6 Maintaining Ordered Data

The Polygon ADT is an example of a mutable ordered sequence. An ordered sequence is a container in which the elements are arranged in linear order from front to back. When the elements of the sequence are accessible by position, as is the case with the Polygon ADT, it is normally referred to as an indexed ordered sequence or simply an indexed sequence. Throughout the text, we assume that access to the individual elements of an indexed sequence is based on their position within the linear order, which is provided using the subscript operator.

Since a polygon is defined by an arbitrary number of vertices (> 3) we will need a way to store the vertices within an instance of the Polygon class. The obvious choice is to represent each vertex using a Point storage object as we did in Section 1.10 for the second implementation of the line segment

class Point :
  def __init__(self, x, y) :
    self.xCoord = x
    self.yCoord = y

and to store the objects within a list. For example, suppose we want to create the following polygon

then we will need to store a collection of Point objects within a list structure as shown below

Unlike the Bag ADT introduced earlier in the chapter, the elements contained in a polygon must be stored or arranged in a specific order. Given the list of points that define the vertices, edges of the polygon are defined between successive points with the last edge formed between the last entry in the list and the first. In addition, we must be able to access the individual vertices by position or index. This is easily done, since the elements of a list structure can themselves be accessed by position.

The Constructor

To implement the Polygon class, we begin with the constructor. The constructor takes six arguments, two for each of the three pairs of vertex coordinates. The vertices will be stored in Point objects within a list. The order in which the vertices are added to the list is important, they must follow the order provided in the argument list.

class Polygon :
  def __init__(self, x0, y0, x1, y1, x2, y2) :
    self._vertexList = list(Point(x0, y0), Point(x1, y1), Point(x2, y2))

A sample instance of the Polygon class is illustrated below

Number of Vertices

Since we are using a list to store the Point objects, one for each vertex, the number of vertices that define the polygon can be obtained from the length of the list.

def __len__(self) :
  return len(self._vertexList)

Finding a Vertex

Accessing the vertex at a given index position is simply a matter of accessing the corresponding element in the list. Of course, we have to check the precondition before attempting to element the list element:

def getVertex(self, index) :
  assert index >=0 and index < len(self), "Index out of range."
  return self._vertexList[index]

The findVertex method is suppose to find and return the index position for a given vertex. While Python's list container includes an index method for just this purpose, we can not use it since the vertices are stored in the list using Point objects. Instead, we have to implement our own search:

def findVertex(self, x, y) :
  for i in range(len(self._vertexList)) :
    vertex = self._vertexList[i]
    if vertex.xCoord == x and vertex.yCoord == y :
      return i
  return -1

Inserting a Vertex

The insertVertex method allows us to modify a polygon by inserting a new vertex at any position between two existing vertices. For example, suppose we want to insert a new vertex (27, 20) into our sample polygon at index position 2, which is between vertices (13, 20) and (27, 10).

Then we would supply the statement

poly.insertVertex(2, 27, 20)

To accomplish this, the method should create a Point object for the new vertex and insert it at the given index position using the insert method on the list. If the index is equal to the number of vertices in the list, then we can simply append it to the end of the list.

vertex = Point(x, y)
if index == len(self) :
  self._vertexList.append(vertex)
else :
  self._vertexList.insert(index, vertex)    

The resulting list after inserting the new vertex would look as follows:

The insertVertex method has two preconditions that must be checked before the new vertex can be added to the list: the index must be within range and the new vertex can not be identical to an existing vertex:

assert index >= 0 and index <= len(self), "Index out of range."
assert self.findVertex(x, y) == -1, "The vertex must be unique."

The full implementation of the insertVertex method follows:

def insertVertex(self, index, x, y) :
  assert index >= 0 and index <= len(self), "Index out of range."
  assert self.findVertex(x, y) == -1, "The vertex must be unique."

  vertex = Point(x, y)
  if index == len(self) :
    self._vertexList.append(vertex)
  else :
    self._vertexList.insert(index, vertex)    

The complete implementation of the Polygon class is provided in the source listing below. The implementation of the remaining methods are left as an exercise.

Program Listing
Program: polygon.py
  1. # Implement of the Polygon ADT container using a list.
  2. class Polygon :
  3.    # Creates a 3-sided polygon defined by the given vertices.
  4.   def __init__(self, x0, y0, x1, y1, x2, y2) :
  5.     self._vertexList = list(Point(x0, y0), Point(x1, y1), Point(x2, y2))
  6.  
  7.    # Returns the number of vertices that comprise the polygon.
  8.   def __len__(self) :
  9.     return len(self._vertexList)
  10.  
  11.    # Finds the index of the given vertex or returns -1.
  12.   def findVertex(self, x, y) :
  13.     for i in range(len(self._vertexList)) :
  14.       vertex = self._vertexList[i]
  15.       if vertex.xCoord == x and vertex.yCoord == y :
  16.         return i
  17.     return -1
  18.    
  19.    # Returns the coordinates of the vertex as the index position.
  20.   def getVertex(self, index) :
  21.     assert index >=0 and index < len(self), "Index out of range."
  22.     return self._vertexList[index]
  23.  
  24.    # Appends a new vertex after the last defined vertex.
  25.   def appendVertex(self, x, y) :
  26.     ......
  27.    
  28.    # Inserts a new vertex at the given index position.
  29.   def insertVertex(self, index, x, y) :
  30.     assert index >= 0 and index <= len(self), "Index out of range."
  31.     assert self.findVertex(x, y) == -1, "The vertex must be unique."
  32.  
  33.     vertex = Point(x, y)
  34.     if index == len(self) :
  35.       self._vertexList.append(vertex)
  36.     else :
  37.       self._vertexList.insert(index, vertex)    
  38.    
  39.    # Removes the vertex at the given index position.
  40.   def deleteVertex(self, index) :
  41.     ......
  42.    
  43.    # Returns the total length of the polygon's perimeter.
  44.   def perimeter(self) :
  45.     ......
  46.  
  47. # Private storage class for representing a 2-D point.
  48. class Point :
  49.   def __init__(self, x, y) :
  50.     self.xCoord = x
  51.     self.yCoord = y      
Page last modified on August 02, 2023, at 09:09 PM