一、Array
1.The array structure
import ctypes
#Array ADT
class Array:
# Creates an array with size elements.
def __init__(self, size):
assert size > 0, "Array size must be > 0"
self._size = size
# Create the array structure using the ctypes module.
PyArrayType = ctypes.py_object * size
self._elements = PyArrayType()
# Initialize each element.
self.clear(None)
def __len__(self):
return self._size
#从这里我们也可以看出为什么len()方法的时间复杂度是O(1)
# Gets the contents of the index element.
def __getitem__(self, index):
assert index >= 0 and index < len(self), "Array subscript out of range"
return self._elements[index]
def __setitem__(self, index, value):
assert index >= 0 and index < len(self), "Array subscript out of range"
self._elements[index] = value
def clear(self, value):
for i in range(len(self)):
self._elements[i] = value
# Returns the array's iterator for traversing the elements.
def __iter__(self):
return _ArrayIterator(self._elements)
#An iterator for the Array ADT.
class _ArrayIterator:
def __init__(self, theArray):
self._arrayRef = theArray
self._curNdx = 0
def __iter__(self):
return self
def __next__(self):
if self._curNdx < len(self._arrayRef):
entry = self._arrayRef[self._curNdx]
self._curNdx += 1
return entry
else:
raise StopIteration
def main():
array = Array(5)
print(array.__len__())
array.clear('a')
arrayIter = array.__iter__()
while True:
try:
x = arrayIter.__next__()
print(x)
except StopIteration:
print('done')
break
print(array[3])
main()
'''
代码运行效果如下:
5
a
a
a
a
a
done
a
从这里我们可以看出,实现了__getitem__()的方法,就可以直接用中括号获取数组(array)的值
'''
2.The 2DArray:
class Array2D:
# Creates a 2-D array of size numRows x numCols.
def __init__(self, numRows, numCols):
# Create a 1-D array to store an array reference for each row.
self._theRows = Array(numRows)
for i in range(numRows):
self._theRows[i] = Array(numCols)
# Returns the number of rows in the 2-D array.
def numRows(self):
return len(self._theRows)
# Returns the number of columns in the 2-D array.
def numCols(self):
return len(self._theRows[0])
def clear(self, value):
for row in range(self.numRows()):
self._theRows[row].clear(value)
def __getitem__(self, ndxTuple):
assert len(ndxTuple) == 2, "Invalid number of array subscripts."
row = ndxTuple[0]
col = ndxTuple[1]
assert row >= 0 and row < self.numRows() \
and col >= 0 and col < self.numCols(), \
"Array subscript out of range."
theldArray = self._theRows[row]
return theldArray[col]
def __setitem__(self, ndxTuple, value):
assert len(ndxTuple) == 2, "Invalid number of array subscripts."
row = ndxTuple[0]
col = ndxTuple[1]
assert row >= 0 and row < self.numRows() \
and col >= 0 and col < self.numCols(), \
"Array subscript out of range."
theldArray = self._theRows[row]
theldArray[col] = value
def main():
array2D = Array2D(5,3)
print(array2D.numCols())
print(array2D.numRows())
array2D.clear('b')
print(array2D.__getitem__((2,1)))
array2D.__setitem__((2,2),'c')
print(array2D.__getitem__((2,2)))
main()
'''
代码运行效果如下:
3
5
b
c
'''
3.Multi-Dimensional Arrays
from array import Array
class MultiArray:
def __init__(self, *dimensions):
assert len(dimensions) > 1, "The array must have 2 or more dimentions."
# The variable argument tuple contains the dim sizes.
self._dims = dimensions
size = 1
for d in dimensions:
assert d > 0, "Dimensions must be > 0."
size *= d
# Create the 1-D array to store the elements.
self._elements = Array(size)
# Create a 1-D array to store the equation factors.
self._factors = Array(len(dimensions))
self._computeFactors()
def numDims(self):
return len(self._dims)
def length(self, dim):
assert dim >= 1 and dim < len(self._dims),\
"Dimensions component out of range."
return self._dims[dim - 1]
def clear(self, value):
self._elements.clear(value)
def __getitem__(self, ndxTuple):
assert len(ndxTuple) == self.numDims(), "Invaid # of array subscrips."
index = self._computeIndex(ndxTuple)
assert index is not None, "Array subscript out of range."
return self._elements[index]
def __setitem__(self, ndxTuple, value):
assert len(ndxTuple) == self.numDims(), "Invaid # of array subscrips."
index = self._computeIndex(ndxTuple)
assert index is not None, "Array subscript out of range."
self._elements[index] = value
def _computeIndex(self, idx):
offset = 0
for j in range(len(idx)):
if idx[j] < 0 or idx[j] >= self._dims[j]:
return None
else:
offset += idx[j] * self._factors[j]
return offset
# Computes the factor values used in the index equation.
def _computeFactors(self):
for i in range(len(self._dims)):
self._factors[i] = self._dims[i]
二、矩阵
1.Matrix
from array import Array2D
class Matrix:
def __init__(self, numRows, numCols):
self._theGrid = Array2D(numRows, numCols)
self._theGrid.clear(0)
def numCols(self):
return self._theGrid.numCols()
def numRows(self):
return self._theGrid.numRows()
def __getitem__(self, ndxTuple):
return self._theGrid[ndxTuple[0],ndxTuple[1]]
def __setitem__(self, ndxTuple, value):
self._theGrid[ndxTuple[0],ndxTuple[1]] = value
def scaleBy(self, scalar):
for r in range(self.numRows()):
for c in range(self.numCols()):
self[r,c] *= scalar
def transpose(self):
NewMatrix = Matrix(self._theGrid.numCols(),
self._theGrid.numRows())
for r in range(self.numRows()):
for c in range(self.numCols()):
NewMatrix[c,r] = self[r,c]
return NewMatrix
def __add__(self, rhsMartix):
assert rhsMartix.numRows() == self.numRows() and \
rhsMartix.numCols() == self.numCols(), \
"Matrix sizes not compatible for the add operation."
newMatrix = Matrix(self.numRows(), self.numCols())
for r in range(self.numRows()):
for c in range(self.numCols()):
newMatrix[r,c] = self[r,c] + rhsMartix[r,c]
return newMatrix
def __sub__(self, rhsMartix):
assert rhsMartix.numRows() == self.numRows() and \
rhsMartix.numCols() == self.numCols(), \
"Matrix sizes not compatible for the add operation."
newMatrix = Matrix(self.numRows(), self.numCols())
for r in range(self.numRows()):
for c in range(self.numCols()):
newMatrix[r,c] = self[r,c] - rhsMartix[r,c]
return newMatrix
def __mul__(self, rhsMartix):
assert self.numCols() == rhsMartix.numRows(), \
"Matrix sizes not compatible for the multiplication operation."
newMatrix = Matrix(self.numRows(), rhsMartix.numCols())
for i in range(self.numRows()):
for j in range(rhsMartix.numCols()):
for k in range(rhsMartix.numRows()):
newMatrix[i,j] += self[i,k] * rhsMartix[k,j]
return newMatrix
2.Sparse Matrix
(1)基于列表
乘法未解决
class SparseMatrix:
def __init__(self, numRows, numCols):
self._numRows = numRows
self._numCols = numCols
self._elementList = list()
def numRows(self):
return self._numRows
def numCols(self):
return self._numCols
def __getitem__(self, ndxTuple):
ndx = self._findPosition(ndxTuple[0], ndxTuple[1])
if ndx is not None:
return self._elementList[ndx].value
else:
return 0.0
def __setitem__(self, ndxTuple, scalar):
ndx = self._findPosition(ndxTuple[0], ndxTuple[1])
if ndx is not None:
if scalar != 0.0:
self._elementList[ndx].value = scalar
else:
self._elementList.pop(ndx)
else:
if scalar != 0.0:
element = _MatrixElement(ndxTuple[0], ndxTuple[1], scalar)
self._elementList.append(element)
def scaleBy(self, scalar):
for element in self._elementList:
element.value *= scalar
def __add__(self, rhsMartix):
assert rhsMartix.numRows() == self.numRows() and \
rhsMartix.numCols() == self.numCols(), \
"Matrix sizes not compatible for the add operation."
newMartix = SparseMatrix(self.numRows(), self.numCols())
for element in self._elementList:
dupElement = _MatrixElement(element.row, element.col, element.value)
newMartix._elementList.append(dupElement)
for element in rhsMartix._elementList:
value = newMartix[element.row, element.col]
value += element.value
newMartix[element.row, element.col] = value
return newMartix
def __sub__(self, rhsMartix):
assert rhsMartix.numRows() == self.numRows() and \
rhsMartix.numCols() == self.numCols(),\
"Matrix sizes not compatible for the add operation."
newMartix = SparseMatrix(self.numRows(), self.numCols())
for element in self._elementList:
dupElement = _MatrixElement(element.row, element.col, element.value)
newMartix._elementList.append(dupElement)
for element in rhsMartix._elementList:
value = newMartix[element.row, element.col]
value -= element.value
newMartix[element.row, element.col] = value
return newMartix
#不知道有没有更好的方法。
def __mul__(self, rhsMartix):
assert self.numCols() == rhsMartix.numRows(),\
"Matrix sizes not compatible for the multiplication operation."
newMatrix = SparseMatrix(self.numRows(), rhsMartix.numCols())
for i in range(self.numRows()):
for j in range(rhsMartix.numCols()):
for k in range(rhsMartix.numRows()):
newMatrix[i,j] += self[i,k] * rhsMartix[k,j]
return newMatrix
def _findPosition(self, row, col):
n = len(self._elementList)
for i in range(n):
if row == self._elementList[i].row and \
col == self._elementList[i].col:
return i
return None
class _MatrixElement:
def __init__(self, row, col, value):
self.row = row
self.col = col
self.value = value
(2)基于单链表
乘法未解决
from array import Array
class SparseMatrix:
def __init__(self, numRows, numCols):
self._numCols = numCols
self._listOfRows = Array(numRows)
def numRows(self):
return len(self._listOfRows)
def numCols(self):
return self._numCols
def __getitem__(self, ndxTuple):
pass
def __setitem__(self, ndxTuple, value):
row = ndxTuple[0]
col = ndxTuple[1]
predNode = None
curNode = self._listOfRows[row]
while curNode is not None and curNode.col != col:
predNode = curNode
curNode = curNode.next
#如果curNode是第一个结点
if curNode is not None and curNode.col == col:
if value == 0.0:
if curNode == self._listOfRows[row]:
self._listOfRows[row] = curNode.next
else:
predNode.next = curNode.next
else:
curNode.value = value
elif value != 0.0:
newNode = _MatrixElementNode(col, value)
newNode.next == curNode
#如果curNode是第一个结点
if curNode == self._listOfRows[row]:
self._listOfRows[row] = newNode
else:
predNode.next = newNode
def scaleBy(self, scalar):
for row in range(self.numRows()):
curNode = self._listOfRows[row]
while curNode is not None:
curNode.value *= scalar
curNode = curNode.next
def transpose(self):
pass
def __add__(self, rhsMatrix):
assert rhsMatrix.numRows() == self.numRows() and \
rhsMatrix.numCols() == self.numCols(),\
"Matrix sizes not compatable for adding."
newMatrix = SparseMatrix(self.numRows, self.numCols())
for row in range(self.numRows()):
curNode = self._listOfRows[row]
while curNode is not None:
newMatrix[row, curNode.col] = curNode.value
curNode = curNode.next
for row in range(rhsMatrix.numRows()):
curNode = rhsMatrix._listOfRows[row]
while curNode is not None:
value = newMatrix[row, curNode.col]
value += curNode.value
newMatrix[row, curNode.col] = value
curNode = curNode.next
return newMatrix
def __sub__(self, rhsMatrix):
assert rhsMatrix.numRows() == self.numRows() and \
rhsMatrix.numCols() == self.numCols(),\
"Matrix sizes not compatable for adding."
newMatrix = SparseMatrix(self.numRows, self.numCols())
for row in range(self.numRows()):
curNode = self._listOfRows[row]
while curNode is not None:
newMatrix[row, curNode.col] = curNode.value
curNode = curNode.next
for row in range(rhsMatrix.numRows()):
curNode = rhsMatrix._listOfRows[row]
while curNode is not None:
value = newMatrix[row, curNode.col]
value -= curNode.value
newMatrix[row, curNode.col] = value
curNode = curNode.next
return newMatrix
def __mul__(self, rhsMatrix):
pass
class _MatrixElementNode:
def __init__(self, col, value):
self.col = col
self.value = value
self.next = None
3.基于多链表
大部分未解决
class MatrixMListNode:
def __init__(self, row, col, value):
self.row = row
self.col = col
self.value = value
self.nextCol = None
self.nextRow = None
class _SparseMatrixIterator:
def __init__(self, rowArray):
self._rowArray = rowArray
self._curRow = 0
self._curNode = None
self._findNextElement()
def __iter__(self):
return self
def __next__(self):
if self._curNode is None:
raise StopIteration
else:
value = self._curNode.value
self._curNode = self._curNode.next
if self._curNode is None:
self._findNextElement()
return value
def _findNextElement(self):
i = self._curRow
while i < len(self._rowArray) and self._rowArray[i] is None:
i += 1
self._curRow = i
if i < len(self._rowArray):
self._curNode = self._rowArray[i]
else:
self._curNode = None
三、The Game of Life
未解决