Python学习笔记(二)——数组与矩阵

一、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

未解决

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值