python数据结构学习笔记-2016-10-28-02-使用链表实现稀疏矩阵

来源:互联网 发布:阿里大鱼 php短信demo 编辑:程序博客网 时间:2024/06/15 02:08

       6.5 使用链表实现稀疏矩阵

       6.5.1 实现

       使用一个数组来储存稀疏矩阵的行,数组的一个元素指向稀疏矩阵的每一行,而每一行的非零元素以链表表示。所以每一个结点只需储存列号和相应的数值即可。



#-*-coding: utf-8-*-# 使用排序链表的数组来实现稀疏矩阵from myarray import Arrayclass SparseMatrix(object):    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):        # 按照相应的行号和列号找出相应结点,若存在        predNode = None        curNode = self._listOfRows[ndxTuple[0]]        while curNode is not None and curNode.col != ndxTuple[1]:            predNode = curNode            curNode = curNode.next        if curNode is not None: # 结点若存在            if value == 0.0: # 传入值为零,需要删除结点                if curNode == self._listOfRows[ndxTuple[0]]: # 要删除的结点就是首元结点                    self._listOfRows[ndxTuple[0]] = curNode.next                else: # 要删除的结点非首元结点                    predNode.next = curNode.next            else: # 结点存在且传入值非零,直接修改节点值即可                curNode.value = value        else: # 结点不存在            if value != 0.0: # 结点不存在其传入值非零,需插入新结点                newNode = _MatrixElementNode(ndxTuple[1], value)                newNode.next = curNode                if curNode == self._listOfRows[ndxTuple[0]]: # 插入的新结点作为首元结点                    self._listOfRows[ndxTuple[0]] = 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, other):        assert self.numRows() == other.numRows() and self.numCols() == other.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(other.numRows()):            while curNode is not None:                newMatrix[row, curNode.col] += curNode.value                curNode = curNode.next        return newMatrix    def substract(self, other):        pass    def multiply(self, other):        pass# 储存类,矩阵元素结点class _MatrixElementNode(object):    def __init__(self, col, value):        self.col = col        self.value = value        self.next = None

       赋值操作比较复杂,按照行号和列号,找出相应的结点,有以下五种情况:

  • 结点存在,传入值非零,直接修改值;
  • 结点存在,传入值为零,需删除结点,要删除的结点是首元结点;
  • 结点存在,传入值为零,需删除结点,要删除的结点是非首元结点;
  • 结点不存在,传入值非零,需添加结点,且插入的结点作为首元结点;
  • 结点不存在,传入值非零,需添加结点,但不足为首元结点。      
       赋值操作的时间复杂度是O(n),最坏情况就是要遍历矩阵的一行。


       数乘运算

       将每一个链表遍历,并进行乘法,其时间复杂度是O(k),其中k是非零元素个数。


       加法运算

       也是先复制一个矩阵的非零元素,再加上另一个矩阵的非零元素。其时间复杂度是O(kn)。书上说是有更为有效的办法,本人理解就是将两个矩阵的每一行的两个链表合并,其时间复杂度是O(k)。


       6.5.2 比较各种实现方法

       k是非零元素个数,n是矩阵的列数(行数)。

操作二维数组就列表链表构造器O(1)O(1)O(1)s.numRows()O(1)O(1)O(1)s.numCols()O(1)O(1)O(1)x = s[i, j]O(1)O(k)O(n)s[i, j] = xO(1)O(k)O(n)s.scaleBy(x)O(n²)O(k)O(k)r = s + tO(n²)O(k²)O(kn)

0 0
原创粉丝点击