Python:稀疏数组与三角数组

  • 稀疏数组

稀疏数组应用场景:
    当数组size很大而空间利用率很低时,应使用稀疏数组来存储
    
下面的实现的稀疏数组0行0列都没用来存储数据,留做存储row_size等其他数据用,一个稀疏数组由多个行链表组成,一个行链表由多个节点构成

Python 实现如下:

# 节点类
class ArrayEntry:
    def __init__(self, columnNumber=0, nextEntry=None, entry=0):
        # 所处的列数
        self.columnNumber = columnNumber
        # 下一个节点
        self.nextEntry = nextEntry
        # 数据域
        self.entry = entry


# 行链表类
class ArrayRow:
    def __init__(self, rowNumber=0, rowSentinel=ArrayEntry(), nextRow=None):
        # 稀疏数组所处的行
        self.rowNumber = rowNumber
        # 下一行
        self.nextRow = nextRow
        # 当前行的哨兵、头指针
        self.rowSentinel = rowSentinel

        self.columnSize = 0


# 稀疏数组类
class SparseArray:
    def __init__(self, sentinel=ArrayRow(), rowSize=0, columnSize=0):
        # sentinel row的头指针
        self.sentinel = sentinel
        # 稀疏数组的行
        self.rowSize = rowSize
        # 稀疏数组的列
        self.columnSize = columnSize

定义操作:

  1. 寻找前一行
# 寻找rowNum前一行,返回rowNum前一行
    def findRowBefore(self, rowNum) -> ArrayRow:
        array_row = self.sentinel
        while array_row.nextRow and array_row.nextRow.rowNumber < rowNum:
            array_row = array_row.nextRow
        return array_row

     2.寻找某一行某个节点的前驱节点

 # 寻找row的columnNum列的前一列
    def findColumnBefore(self, row, columnNum) -> ArrayEntry or str:
        if row is None:
            return "row 不能为空"
        row_sentinel = row.rowSentinel
        while row_sentinel.nextEntry and row_sentinel.nextEntry.columnNumber < columnNum:
            row_sentinel = row_sentinel.nextEntry
        return row_sentinel

      3.获取值


    # 获取(rowNum,columnNum)值
    def getEntry(self, rowNum, columnNum) -> int or str:
        row = self.findRowBefore(rowNum)
        if row.nextRow is None or row.nextRow.rowNumber > rowNum:
            return "没找到行" + str(rowNum)
        row_sentinel = self.findColumnBefore(row, columnNum)
        if row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
            return "没找到列" + str(columnNum)
        return row_sentinel.nextEntry.entry

     4.设置值

# 设置entry,若未找到行,则新建行,未找到列则,新建列
    def setEntry(self, rowNum, columnNum, entry) -> bool:
        # 找到行
        row = self.findRowBefore(rowNum)
        if row.nextRow is None or row.nextRow.rowNumber > rowNum:
            new_row = ArrayRow(row.rowNumber + 1)
            new_row.nextRow = row.nextRow
            row.nextRow = new_row
            row = row.nextRow

        # 找到列
        row_sentinel = self.findColumnBefore(row, columnNum)
        if type(row_sentinel) == str:
            return False
        elif row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
            new_column = ArrayEntry(columnNumber=row_sentinel.columnNumber + 1, entry=entry)
            new_column.nextEntry = row_sentinel.nextEntry
            row_sentinel.nextEntry = new_column
        else:
            row_sentinel.nextEntry.entry = entry
        return True

5.删除节点

def deleteEntry(self, rowNum, columnNum):
    # 找到行
    row = self.findRowBefore(rowNum)
    if row.nextRow is None or row.nextRow.rowNumber > rowNum:
        return False

    # 找到列
    row_sentinel = self.findColumnBefore(row.nextRow, columnNum)
    if type(row_sentinel) == str:
        return False
    elif row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
        return False
    else:
        delete = row_sentinel.nextEntry
        after_delete = row_sentinel.nextEntry.nextEntry
        row_sentinel.nextEntry = after_delete
        # 如果 列被删除后,该行已没有列,删除该行
        if after_delete is None and row_sentinel.columnNumber == 0:
            row.nextRow = None
        del delete
        gc.collect()
        return True

6.矩阵加法

稀疏矩阵加法(伪代码):
    遍历两个矩阵行,
    while arr1 and arr2:
        if arr1.rowNum>arr2.rowNum : add arr2 to result,arr2=arr2.nextRow
        elif arr1.rowNum<arr2.rowNum : add arr1 to result,arr1 = arr1.nextRow
        else add arr1[rowNum] + arr2[rowNum] to result,arr1 = arr1.nextRow,arr2=arr2.nextRow
    
    add arr1 remaining to result
    add arr2 remaining to result

7.矩阵乘法

稀疏矩阵乘法:
    对与矩阵arr1*arr2,由与 要遍历arr2的每一列,而列不能迭代,
    我们可以将arr2转置,转制后的矩阵arr2的一行就是转置之前的一列,
    若entry默认值为零,类似加法,乘法可计算如下:
        遍历arr1,与arr2的转置,
            若对于arr1.rowNum != arr2转置.rowNum,点(arr1.rowNum,arr2转置.rowNum)为0
            若对于arr1.rowNum == arr2转置.rowNum,则点(arr1.rowNum,arr2转置.rowNum)为对应项乘积之和
  • 三角矩阵

应用场景:面对size庞大的数组,且当数组具有很好的对称性时,可以使用三角矩阵,如无向图的邻接矩阵等。
特点:一维矩阵表示二维矩阵,[i,j] === ((i-1)**2+i-1)/2 +j(数组下表从1开始),[i,j] === (i**2+i)/2 +j(数组下表从0开始)

Python实现:

import time

from pymysql import Date

"""
    应用场景:数组对称
"""


class TriangleArray:
    def __init__(self):
        self.data = []
        self.size = 0

    def get(self, row, column):
        index = int((row ** 2 + row) / 2 + column)
        if index <= self.size - 1:
            return self.data[index]
        else:
            return None

    def append_(self, value):
        self.data.append(value)
        self.size += 1

    def set(self, row, column, value):
        index = int((row ** 2 + row) / 2 + column)
        if index <= self.size - 1:
            self.data[index] = value
            return True
        else:
            return False


if __name__ == "__main__":
    tri = TriangleArray()
    tri.append_(1)
    tri.append_("rlyslata")
    tri.append_("CSDN")
    tri.append_("新肺炎冠状病毒")
    tri.append_(str(time.localtime()))

    print(tri.get(0, 0))
    print(tri.get(1, 0))
    print(tri.get(1, 1))
    print(tri.get(2, 0))
    print(tri.get(2, 1))

 

PS:代码clone地址:git@github.com:Rlyslata/DataStauct-And-Algorithm.git 

       路径:关于链表的算法/SparseArray    关于链表的算法/TriangleArray

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值